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 public Tag(byte[] bytes, int offset, int length) {
106 if (length > MAX_TAG_LENGTH) {
107 throw new IllegalArgumentException(
108 "Invalid tag data being passed. Its length can not exceed " + MAX_TAG_LENGTH);
109 }
110 this.bytes = bytes;
111 this.offset = offset;
112 this.length = length;
113 this.type = bytes[offset + TAG_LENGTH_SIZE];
114 }
115
116
117
118
119 public byte[] getBuffer() {
120 return this.bytes;
121 }
122
123
124
125
126 public byte getType() {
127 return this.type;
128 }
129
130
131
132
133 public int getTagLength() {
134 return this.length - INFRASTRUCTURE_SIZE;
135 }
136
137
138
139
140 public int getTagOffset() {
141 return this.offset + INFRASTRUCTURE_SIZE;
142 }
143
144
145
146
147
148
149
150
151 public byte[] getValue() {
152 int tagLength = getTagLength();
153 byte[] tag = new byte[tagLength];
154 Bytes.putBytes(tag, 0, bytes, getTagOffset(), tagLength);
155 return tag;
156 }
157
158
159
160
161
162
163
164
165
166 public static List<Tag> asList(byte[] b, int offset, int length) {
167 List<Tag> tags = new ArrayList<Tag>();
168 int pos = offset;
169 while (pos < offset + length) {
170 int tagLen = Bytes.readAsInt(b, pos, TAG_LENGTH_SIZE);
171 tags.add(new Tag(b, pos, tagLen + TAG_LENGTH_SIZE));
172 pos += TAG_LENGTH_SIZE + tagLen;
173 }
174 return tags;
175 }
176
177
178
179
180
181
182 public static byte[] fromList(List<Tag> tags) {
183 int length = 0;
184 for (Tag tag: tags) {
185 length += tag.length;
186 }
187 byte[] b = new byte[length];
188 int pos = 0;
189 for (Tag tag: tags) {
190 System.arraycopy(tag.bytes, tag.offset, b, pos, tag.length);
191 pos += tag.length;
192 }
193 return b;
194 }
195
196
197
198
199
200
201
202
203
204 public static Tag getTag(byte[] b, int offset, int length, byte type) {
205 int pos = offset;
206 while (pos < offset + length) {
207 int tagLen = Bytes.readAsInt(b, pos, TAG_LENGTH_SIZE);
208 if(b[pos + TAG_LENGTH_SIZE] == type) {
209 return new Tag(b, pos, tagLen + TAG_LENGTH_SIZE);
210 }
211 pos += TAG_LENGTH_SIZE + tagLen;
212 }
213 return null;
214 }
215
216
217
218
219 int getLength() {
220 return this.length;
221 }
222
223
224
225
226 int getOffset() {
227 return this.offset;
228 }
229 }