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