1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package org.apache.hadoop.hbase.util;
18
19 import java.io.ByteArrayOutputStream;
20 import java.io.DataInputStream;
21 import java.io.IOException;
22 import java.io.InputStream;
23 import java.io.OutputStream;
24 import java.nio.ByteBuffer;
25
26 import org.apache.hadoop.hbase.classification.InterfaceAudience;
27 import org.apache.hadoop.hbase.classification.InterfaceStability;
28 import org.apache.hadoop.io.IOUtils;
29 import org.apache.hadoop.io.WritableUtils;
30
31
32
33
34
35 @InterfaceAudience.Public
36 @InterfaceStability.Evolving
37 public final class ByteBufferUtils {
38
39
40 private final static int VALUE_MASK = 0x7f;
41 private final static int NEXT_BIT_SHIFT = 7;
42 private final static int NEXT_BIT_MASK = 1 << 7;
43
44 private ByteBufferUtils() {
45 }
46
47
48
49
50
51 public static void writeVLong(ByteBuffer out, long i) {
52 if (i >= -112 && i <= 127) {
53 out.put((byte) i);
54 return;
55 }
56
57 int len = -112;
58 if (i < 0) {
59 i ^= -1L;
60 len = -120;
61 }
62
63 long tmp = i;
64 while (tmp != 0) {
65 tmp = tmp >> 8;
66 len--;
67 }
68
69 out.put((byte) len);
70
71 len = (len < -120) ? -(len + 120) : -(len + 112);
72
73 for (int idx = len; idx != 0; idx--) {
74 int shiftbits = (idx - 1) * 8;
75 long mask = 0xFFL << shiftbits;
76 out.put((byte) ((i & mask) >> shiftbits));
77 }
78 }
79
80
81
82
83
84 public static long readVLong(ByteBuffer in) {
85 byte firstByte = in.get();
86 int len = WritableUtils.decodeVIntSize(firstByte);
87 if (len == 1) {
88 return firstByte;
89 }
90 long i = 0;
91 for (int idx = 0; idx < len-1; idx++) {
92 byte b = in.get();
93 i = i << 8;
94 i = i | (b & 0xFF);
95 }
96 return (WritableUtils.isNegativeVInt(firstByte) ? (i ^ -1L) : i);
97 }
98
99
100
101
102
103
104
105
106
107
108
109 public static int putCompressedInt(OutputStream out, final int value)
110 throws IOException {
111 int i = 0;
112 int tmpvalue = value;
113 do {
114 byte b = (byte) (tmpvalue & VALUE_MASK);
115 tmpvalue >>>= NEXT_BIT_SHIFT;
116 if (tmpvalue != 0) {
117 b |= (byte) NEXT_BIT_MASK;
118 }
119 out.write(b);
120 i++;
121 } while (tmpvalue != 0);
122 return i;
123 }
124
125
126
127
128
129
130
131 public static void putInt(OutputStream out, final int value)
132 throws IOException {
133 for (int i = Bytes.SIZEOF_INT - 1; i >= 0; --i) {
134 out.write((byte) (value >>> (i * 8)));
135 }
136 }
137
138
139
140
141
142
143
144 public static void moveBufferToStream(OutputStream out, ByteBuffer in,
145 int length) throws IOException {
146 copyBufferToStream(out, in, in.position(), length);
147 skip(in, length);
148 }
149
150
151
152
153
154
155
156
157
158
159 public static void copyBufferToStream(OutputStream out, ByteBuffer in,
160 int offset, int length) throws IOException {
161 if (in.hasArray()) {
162 out.write(in.array(), in.arrayOffset() + offset,
163 length);
164 } else {
165 for (int i = 0; i < length; ++i) {
166 out.write(in.get(offset + i));
167 }
168 }
169 }
170
171 public static int putLong(OutputStream out, final long value,
172 final int fitInBytes) throws IOException {
173 long tmpValue = value;
174 for (int i = 0; i < fitInBytes; ++i) {
175 out.write((byte) (tmpValue & 0xff));
176 tmpValue >>>= 8;
177 }
178 return fitInBytes;
179 }
180
181
182
183
184
185
186 public static int longFitsIn(final long value) {
187 if (value < 0) {
188 return 8;
189 }
190
191 if (value < (1l << 4 * 8)) {
192
193 if (value < (1l << 2 * 8)) {
194 if (value < (1l << 1 * 8)) {
195 return 1;
196 }
197 return 2;
198 }
199 if (value < (1l << 3 * 8)) {
200 return 3;
201 }
202 return 4;
203 }
204
205 if (value < (1l << 6 * 8)) {
206 if (value < (1l << 5 * 8)) {
207 return 5;
208 }
209 return 6;
210 }
211 if (value < (1l << 7 * 8)) {
212 return 7;
213 }
214 return 8;
215 }
216
217
218
219
220
221
222 public static int intFitsIn(final int value) {
223 if (value < 0) {
224 return 4;
225 }
226
227 if (value < (1 << 2 * 8)) {
228 if (value < (1 << 1 * 8)) {
229 return 1;
230 }
231 return 2;
232 }
233 if (value <= (1 << 3 * 8)) {
234 return 3;
235 }
236 return 4;
237 }
238
239
240
241
242
243
244 public static int readCompressedInt(InputStream input)
245 throws IOException {
246 int result = 0;
247 int i = 0;
248 byte b;
249 do {
250 b = (byte) input.read();
251 result += (b & VALUE_MASK) << (NEXT_BIT_SHIFT * i);
252 i++;
253 if (i > Bytes.SIZEOF_INT + 1) {
254 throw new IllegalStateException(
255 "Corrupted compressed int (too long: " + (i + 1) + " bytes)");
256 }
257 } while (0 != (b & NEXT_BIT_MASK));
258 return result;
259 }
260
261
262
263
264
265 public static int readCompressedInt(ByteBuffer buffer) {
266 byte b = buffer.get();
267 if ((b & NEXT_BIT_MASK) != 0) {
268 return (b & VALUE_MASK) + (readCompressedInt(buffer) << NEXT_BIT_SHIFT);
269 }
270 return b & VALUE_MASK;
271 }
272
273
274
275
276
277
278
279 public static long readLong(InputStream in, final int fitInBytes)
280 throws IOException {
281 long tmpLong = 0;
282 for (int i = 0; i < fitInBytes; ++i) {
283 tmpLong |= (in.read() & 0xffl) << (8 * i);
284 }
285 return tmpLong;
286 }
287
288
289
290
291
292
293 public static long readLong(ByteBuffer in, final int fitInBytes) {
294 long tmpLength = 0;
295 for (int i = 0; i < fitInBytes; ++i) {
296 tmpLength |= (in.get() & 0xffl) << (8l * i);
297 }
298 return tmpLength;
299 }
300
301
302
303
304
305
306
307
308 public static void copyFromStreamToBuffer(ByteBuffer out,
309 DataInputStream in, int length) throws IOException {
310 if (out.hasArray()) {
311 in.readFully(out.array(), out.position() + out.arrayOffset(),
312 length);
313 skip(out, length);
314 } else {
315 for (int i = 0; i < length; ++i) {
316 out.put(in.readByte());
317 }
318 }
319 }
320
321
322
323
324 public static ByteBuffer drainInputStreamToBuffer(InputStream is) throws IOException {
325 ByteArrayOutputStream baos = new ByteArrayOutputStream(4096);
326 IOUtils.copyBytes(is, baos, 4096, true);
327 ByteBuffer buffer = ByteBuffer.wrap(baos.toByteArray());
328 buffer.rewind();
329 return buffer;
330 }
331
332
333
334
335
336
337
338
339
340
341
342 public static void copyFromBufferToBuffer(ByteBuffer out,
343 ByteBuffer in, int sourceOffset, int length) {
344 if (in.hasArray() && out.hasArray()) {
345 System.arraycopy(in.array(), sourceOffset + in.arrayOffset(),
346 out.array(), out.position() +
347 out.arrayOffset(), length);
348 skip(out, length);
349 } else {
350 for (int i = 0; i < length; ++i) {
351 out.put(in.get(sourceOffset + i));
352 }
353 }
354 }
355
356
357
358
359
360
361
362
363
364
365 public static void copyFromBufferToBuffer(ByteBuffer out, ByteBuffer in, int sourceOffset,
366 int destinationOffset, int length) {
367 if (in.hasArray() && out.hasArray()) {
368 System.arraycopy(in.array(), sourceOffset + in.arrayOffset(), out.array(), out.arrayOffset()
369 + destinationOffset, length);
370 } else {
371 for (int i = 0; i < length; ++i) {
372 out.put((destinationOffset + i), in.get(sourceOffset + i));
373 }
374 }
375 }
376
377
378
379
380
381
382
383
384
385 public static int findCommonPrefix(ByteBuffer buffer, int offsetLeft,
386 int offsetRight, int limit) {
387 int prefix = 0;
388
389 for (; prefix < limit; ++prefix) {
390 if (buffer.get(offsetLeft + prefix) != buffer.get(offsetRight + prefix)) {
391 break;
392 }
393 }
394
395 return prefix;
396 }
397
398
399
400
401
402
403
404
405
406
407 public static int findCommonPrefix(
408 byte[] left, int leftOffset, int leftLength,
409 byte[] right, int rightOffset, int rightLength) {
410 int length = Math.min(leftLength, rightLength);
411 int result = 0;
412
413 while (result < length &&
414 left[leftOffset + result] == right[rightOffset + result]) {
415 result++;
416 }
417
418 return result;
419 }
420
421
422
423
424
425
426
427
428
429
430 public static boolean arePartsEqual(ByteBuffer buffer,
431 int offsetLeft, int lengthLeft,
432 int offsetRight, int lengthRight) {
433 if (lengthLeft != lengthRight) {
434 return false;
435 }
436
437 if (buffer.hasArray()) {
438 return 0 == Bytes.compareTo(
439 buffer.array(), buffer.arrayOffset() + offsetLeft, lengthLeft,
440 buffer.array(), buffer.arrayOffset() + offsetRight, lengthRight);
441 }
442
443 for (int i = 0; i < lengthRight; ++i) {
444 if (buffer.get(offsetLeft + i) != buffer.get(offsetRight + i)) {
445 return false;
446 }
447 }
448 return true;
449 }
450
451
452
453
454
455
456 public static void skip(ByteBuffer buffer, int length) {
457 buffer.position(buffer.position() + length);
458 }
459
460 public static void extendLimit(ByteBuffer buffer, int numBytes) {
461 buffer.limit(buffer.limit() + numBytes);
462 }
463
464
465
466
467
468
469
470
471 public static byte[] toBytes(ByteBuffer buffer, int startPosition) {
472 int originalPosition = buffer.position();
473 byte[] output = new byte[buffer.limit() - startPosition];
474 buffer.position(startPosition);
475 buffer.get(output);
476 buffer.position(originalPosition);
477 return output;
478 }
479
480
481
482
483
484
485
486
487 public static byte[] toBytes(ByteBuffer buffer, int offset, int length) {
488 byte[] output = new byte[length];
489 for (int i = 0; i < length; i++) {
490 output[i] = buffer.get(offset + i);
491 }
492 return output;
493 }
494
495 public static int compareTo(ByteBuffer buf1, int o1, int len1, ByteBuffer buf2, int o2, int len2) {
496 if (buf1.hasArray() && buf2.hasArray()) {
497 return Bytes.compareTo(buf1.array(), buf1.arrayOffset() + o1, len1, buf2.array(),
498 buf2.arrayOffset() + o2, len2);
499 }
500 int end1 = o1 + len1;
501 int end2 = o2 + len2;
502 for (int i = o1, j = o2; i < end1 && j < end2; i++, j++) {
503 int a = buf1.get(i) & 0xFF;
504 int b = buf2.get(j) & 0xFF;
505 if (a != b) {
506 return a - b;
507 }
508 }
509 return len1 - len2;
510 }
511 }