1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 package org.apache.hadoop.hbase.util;
20
21 import org.apache.hadoop.classification.InterfaceAudience;
22 import org.apache.hadoop.classification.InterfaceStability;
23
24
25
26
27 @InterfaceAudience.Public
28 @InterfaceStability.Evolving
29 public class SimpleByteRange implements ByteRange {
30
31 private static final int UNSET_HASH_VALUE = -1;
32
33
34
35
36
37
38
39 protected byte[] bytes;
40
41
42
43
44
45 protected int offset;
46
47
48
49
50 protected int length;
51
52
53
54
55
56 private int hash = UNSET_HASH_VALUE;
57
58
59
60
61
62 public SimpleByteRange() {
63 unset();
64 }
65
66
67
68
69
70
71
72 public SimpleByteRange(int capacity) {
73 this(new byte[capacity]);
74 }
75
76
77
78
79
80 public SimpleByteRange(byte[] bytes) {
81 set(bytes);
82 }
83
84
85
86
87
88
89
90
91 public SimpleByteRange(byte[] bytes, int offset, int length) {
92 set(bytes, offset, length);
93 }
94
95
96
97
98
99 @Override
100 public byte[] getBytes() {
101 return bytes;
102 }
103
104 @Override
105 public ByteRange unset() {
106 clearHashCache();
107 this.bytes = null;
108 this.offset = 0;
109 this.length = 0;
110 return this;
111 }
112
113 @Override
114 public ByteRange set(int capacity) {
115 return set(new byte[capacity]);
116 }
117
118 @Override
119 public ByteRange set(byte[] bytes) {
120 if (null == bytes) return unset();
121 clearHashCache();
122 this.bytes = bytes;
123 this.offset = 0;
124 this.length = bytes.length;
125 return this;
126 }
127
128 @Override
129 public ByteRange set(byte[] bytes, int offset, int length) {
130 if (null == bytes) return unset();
131 clearHashCache();
132 this.bytes = bytes;
133 this.offset = offset;
134 this.length = length;
135 return this;
136 }
137
138 @Override
139 public int getOffset() {
140 return offset;
141 }
142
143 @Override
144 public ByteRange setOffset(int offset) {
145 clearHashCache();
146 this.offset = offset;
147 return this;
148 }
149
150 @Override
151 public int getLength() {
152 return length;
153 }
154
155 @Override
156 public ByteRange setLength(int length) {
157 clearHashCache();
158 this.length = length;
159 return this;
160 }
161
162 @Override
163 public boolean isEmpty() {
164 return isEmpty(this);
165 }
166
167
168
169
170 public static boolean isEmpty(ByteRange range) {
171 return range == null || range.getLength() == 0;
172 }
173
174
175
176
177
178 @Override
179 public byte get(int index) {
180 return bytes[offset + index];
181 }
182
183 @Override
184 public ByteRange get(int index, byte[] dst) {
185 if (0 == dst.length) return this;
186 return get(index, dst, 0, dst.length);
187 }
188
189 @Override
190 public ByteRange get(int index, byte[] dst, int offset, int length) {
191 if (0 == length) return this;
192 System.arraycopy(this.bytes, this.offset + index, dst, offset, length);
193 return this;
194 }
195
196 @Override
197 public ByteRange put(int index, byte val) {
198 bytes[offset + index] = val;
199 return this;
200 }
201
202 @Override
203 public ByteRange put(int index, byte[] val) {
204 if (0 == val.length) return this;
205 return put(index, val, 0, val.length);
206 }
207
208 @Override
209 public ByteRange put(int index, byte[] val, int offset, int length) {
210 if (0 == length) return this;
211 System.arraycopy(val, offset, this.bytes, this.offset + index, length);
212 return this;
213 }
214
215
216
217
218
219 @Override
220 public byte[] deepCopyToNewArray() {
221 byte[] result = new byte[length];
222 System.arraycopy(bytes, offset, result, 0, length);
223 return result;
224 }
225
226 @Override
227 public ByteRange deepCopy() {
228 SimpleByteRange clone = new SimpleByteRange(deepCopyToNewArray());
229 if (isHashCached()) {
230 clone.hash = hash;
231 }
232 return clone;
233 }
234
235 @Override
236 public void deepCopyTo(byte[] destination, int destinationOffset) {
237 System.arraycopy(bytes, offset, destination, destinationOffset, length);
238 }
239
240 @Override
241 public void deepCopySubRangeTo(int innerOffset, int copyLength, byte[] destination,
242 int destinationOffset) {
243 System.arraycopy(bytes, offset + innerOffset, destination, destinationOffset, copyLength);
244 }
245
246 @Override
247 public ByteRange shallowCopy() {
248 SimpleByteRange clone = new SimpleByteRange(bytes, offset, length);
249 if (isHashCached()) {
250 clone.hash = hash;
251 }
252 return clone;
253 }
254
255 @Override
256 public ByteRange shallowCopySubRange(int innerOffset, int copyLength) {
257 SimpleByteRange clone = new SimpleByteRange(bytes, offset + innerOffset, copyLength);
258 if (isHashCached()) {
259 clone.hash = hash;
260 }
261 return clone;
262 }
263
264
265
266
267
268 @Override
269 public boolean equals(Object thatObject) {
270 if (thatObject == null){
271 return false;
272 }
273 if (this == thatObject) {
274 return true;
275 }
276 if (hashCode() != thatObject.hashCode()) {
277 return false;
278 }
279 if (!(thatObject instanceof SimpleByteRange)) {
280 return false;
281 }
282 SimpleByteRange that = (SimpleByteRange) thatObject;
283 return Bytes.equals(bytes, offset, length, that.bytes, that.offset, that.length);
284 }
285
286 @Override
287 public int hashCode() {
288 if (isHashCached()) {
289 return hash;
290 }
291 if (this.isEmpty()) {
292 hash = 0;
293 return hash;
294 }
295 int off = offset;
296 hash = 0;
297 for (int i = 0; i < length; i++) {
298 hash = 31 * hash + bytes[off++];
299 }
300 return hash;
301 }
302
303 private boolean isHashCached() {
304 return hash != UNSET_HASH_VALUE;
305 }
306
307 protected void clearHashCache() {
308 hash = UNSET_HASH_VALUE;
309 }
310
311
312
313
314
315 @Override
316 public int compareTo(ByteRange other) {
317 return Bytes.compareTo(bytes, offset, length, other.getBytes(), other.getOffset(),
318 other.getLength());
319 }
320
321 @Override
322 public String toString() {
323 return Bytes.toStringBinary(bytes, offset, length);
324 }
325 }