1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20 package org.apache.hadoop.hbase;
21
22 import java.util.ArrayList;
23 import java.util.List;
24
25 import org.apache.hadoop.hbase.classification.InterfaceAudience;
26 import org.apache.hadoop.hbase.classification.InterfaceStability;
27 import org.apache.hadoop.hbase.util.Bytes;
28
29
30
31
32 @InterfaceAudience.Private
33 @InterfaceStability.Evolving
34 public class Tag {
35 public final static int TYPE_LENGTH_SIZE = Bytes.SIZEOF_BYTE;
36 public final static int TAG_LENGTH_SIZE = Bytes.SIZEOF_SHORT;
37 public final static int INFRASTRUCTURE_SIZE = TYPE_LENGTH_SIZE + TAG_LENGTH_SIZE;
38 public static final int MAX_TAG_LENGTH = (2 * Short.MAX_VALUE) + 1 - TAG_LENGTH_SIZE;
39
40 private final byte type;
41 private final byte[] bytes;
42 private int offset = 0;
43 private int length = 0;
44
45
46
47
48
49 public Tag(byte tagType, String tag) {
50 this(tagType, Bytes.toBytes(tag));
51 }
52
53
54
55
56
57 public Tag(byte tagType, byte[] tag) {
58
59
60
61
62
63 int tagLength = tag.length + TYPE_LENGTH_SIZE;
64 if (tagLength > MAX_TAG_LENGTH) {
65 throw new IllegalArgumentException(
66 "Invalid tag data being passed. Its length can not exceed " + MAX_TAG_LENGTH);
67 }
68 length = TAG_LENGTH_SIZE + tagLength;
69 bytes = new byte[length];
70 int pos = Bytes.putAsShort(bytes, 0, tagLength);
71 pos = Bytes.putByte(bytes, pos, tagType);
72 Bytes.putBytes(bytes, pos, tag, 0, tag.length);
73 this.type = tagType;
74 }
75
76
77
78
79
80
81
82
83
84
85
86 public Tag(byte[] bytes, int offset) {
87 this(bytes, offset, getLength(bytes, offset));
88 }
89
90 private static int getLength(byte[] bytes, int offset) {
91 return TAG_LENGTH_SIZE + Bytes.readAsInt(bytes, offset, TAG_LENGTH_SIZE);
92 }
93
94
95
96
97
98
99
100
101
102
103
104
105
106 @Deprecated
107 public Tag(byte[] bytes, int offset, short length) {
108 this(bytes, offset, (int) length);
109 }
110
111
112
113
114
115
116
117
118
119
120
121
122 public Tag(byte[] bytes, int offset, int length) {
123 if (length > MAX_TAG_LENGTH) {
124 throw new IllegalArgumentException(
125 "Invalid tag data being passed. Its length can not exceed " + MAX_TAG_LENGTH);
126 }
127 this.bytes = bytes;
128 this.offset = offset;
129 this.length = length;
130 this.type = bytes[offset + TAG_LENGTH_SIZE];
131 }
132
133
134
135
136 public byte[] getBuffer() {
137 return this.bytes;
138 }
139
140
141
142
143 public byte getType() {
144 return this.type;
145 }
146
147
148
149
150 public int getTagLength() {
151 return this.length - INFRASTRUCTURE_SIZE;
152 }
153
154
155
156
157 public int getTagOffset() {
158 return this.offset + INFRASTRUCTURE_SIZE;
159 }
160
161
162
163
164
165
166
167
168 public byte[] getValue() {
169 int tagLength = getTagLength();
170 byte[] tag = new byte[tagLength];
171 Bytes.putBytes(tag, 0, bytes, getTagOffset(), tagLength);
172 return tag;
173 }
174
175
176
177
178
179
180
181
182
183 public static List<Tag> asList(byte[] b, int offset, int length) {
184 List<Tag> tags = new ArrayList<Tag>();
185 int pos = offset;
186 while (pos < offset + length) {
187 int tagLen = Bytes.readAsInt(b, pos, TAG_LENGTH_SIZE);
188 tags.add(new Tag(b, pos, tagLen + TAG_LENGTH_SIZE));
189 pos += TAG_LENGTH_SIZE + tagLen;
190 }
191 return tags;
192 }
193
194
195
196
197
198
199
200 public static byte[] fromList(List<Tag> tags) {
201 int length = 0;
202 for (Tag tag : tags) {
203 length += tag.length;
204 }
205 byte[] b = new byte[length];
206 int pos = 0;
207 for (Tag tag : tags) {
208 System.arraycopy(tag.bytes, tag.offset, b, pos, tag.length);
209 pos += tag.length;
210 }
211 return b;
212 }
213
214
215
216
217
218
219
220
221
222 public static Tag getTag(byte[] b, int offset, int length, byte type) {
223 int pos = offset;
224 while (pos < offset + length) {
225 int tagLen = Bytes.readAsInt(b, pos, TAG_LENGTH_SIZE);
226 if(b[pos + TAG_LENGTH_SIZE] == type) {
227 return new Tag(b, pos, tagLen + TAG_LENGTH_SIZE);
228 }
229 pos += TAG_LENGTH_SIZE + tagLen;
230 }
231 return null;
232 }
233
234
235
236
237 int getLength() {
238 return this.length;
239 }
240
241
242
243
244 int getOffset() {
245 return this.offset;
246 }
247 }