2 * Licensed to the Apache Software Foundation (ASF) under one
3 * or more contributor license agreements. See the NOTICE file
4 * distributed with this work for additional information
5 * regarding copyright ownership. The ASF licenses this file
6 * to you under the Apache License, Version 2.0 (the
7 * "License"); you may not use this file except in compliance
8 * with the License. You may obtain a copy of the License at
10 * http://www.apache.org/licenses/LICENSE-2.0
12 * Unless required by applicable law or agreed to in writing, software
13 * distributed under the License is distributed on an "AS IS" BASIS,
14 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 * See the License for the specific language governing permissions and
16 * limitations under the License.
18 package org
.apache
.hadoop
.hbase
.util
;
20 import static org
.apache
.hbase
.thirdparty
.com
.google
.common
.base
.Preconditions
.checkArgument
;
21 import static org
.apache
.hbase
.thirdparty
.com
.google
.common
.base
.Preconditions
.checkNotNull
;
22 import static org
.apache
.hbase
.thirdparty
.com
.google
.common
.base
.Preconditions
.checkPositionIndex
;
24 import java
.io
.DataInput
;
25 import java
.io
.DataOutput
;
26 import java
.io
.IOException
;
27 import java
.io
.UnsupportedEncodingException
;
28 import java
.math
.BigDecimal
;
29 import java
.math
.BigInteger
;
30 import java
.nio
.ByteBuffer
;
31 import java
.nio
.charset
.StandardCharsets
;
32 import java
.security
.SecureRandom
;
33 import java
.util
.ArrayList
;
34 import java
.util
.Arrays
;
35 import java
.util
.Collection
;
36 import java
.util
.Collections
;
37 import java
.util
.Comparator
;
38 import java
.util
.Iterator
;
39 import java
.util
.List
;
40 import java
.util
.Random
;
42 import org
.apache
.hadoop
.hbase
.Cell
;
43 import org
.apache
.hadoop
.hbase
.CellComparator
;
44 import org
.apache
.hadoop
.hbase
.unsafe
.HBasePlatformDependent
;
45 import org
.apache
.hadoop
.io
.RawComparator
;
46 import org
.apache
.hadoop
.io
.WritableComparator
;
47 import org
.apache
.hadoop
.io
.WritableUtils
;
48 import org
.apache
.yetus
.audience
.InterfaceAudience
;
49 import org
.slf4j
.Logger
;
50 import org
.slf4j
.LoggerFactory
;
52 import org
.apache
.hbase
.thirdparty
.org
.apache
.commons
.collections4
.CollectionUtils
;
55 * Utility class that handles byte arrays, conversions to/from other types,
56 * comparisons, hash code generation, manufacturing keys for HashMaps or
57 * HashSets, and can be used as key in maps or trees.
59 @InterfaceAudience.Public
60 @edu.umd
.cs
.findbugs
.annotations
.SuppressWarnings(
61 value
="EQ_CHECK_FOR_OPERAND_NOT_COMPATIBLE_WITH_THIS",
62 justification
="It has been like this forever")
63 public class Bytes
implements Comparable
<Bytes
> {
65 // Using the charset canonical name for String/byte[] conversions is much
66 // more efficient due to use of cached encoders/decoders.
67 private static final String UTF8_CSN
= StandardCharsets
.UTF_8
.name();
69 //HConstants.EMPTY_BYTE_ARRAY should be updated if this changed
70 private static final byte [] EMPTY_BYTE_ARRAY
= new byte [0];
72 private static final Logger LOG
= LoggerFactory
.getLogger(Bytes
.class);
75 * Size of boolean in bytes
77 public static final int SIZEOF_BOOLEAN
= Byte
.SIZE
/ Byte
.SIZE
;
80 * Size of byte in bytes
82 public static final int SIZEOF_BYTE
= SIZEOF_BOOLEAN
;
85 * Size of char in bytes
87 public static final int SIZEOF_CHAR
= Character
.SIZE
/ Byte
.SIZE
;
90 * Size of double in bytes
92 public static final int SIZEOF_DOUBLE
= Double
.SIZE
/ Byte
.SIZE
;
95 * Size of float in bytes
97 public static final int SIZEOF_FLOAT
= Float
.SIZE
/ Byte
.SIZE
;
100 * Size of int in bytes
102 public static final int SIZEOF_INT
= Integer
.SIZE
/ Byte
.SIZE
;
105 * Size of long in bytes
107 public static final int SIZEOF_LONG
= Long
.SIZE
/ Byte
.SIZE
;
110 * Size of short in bytes
112 public static final int SIZEOF_SHORT
= Short
.SIZE
/ Byte
.SIZE
;
115 * Mask to apply to a long to reveal the lower int only. Use like this:
116 * int i = (int)(0xFFFFFFFF00000000L ^ some_long_value);
118 public static final long MASK_FOR_LOWER_INT_IN_LONG
= 0xFFFFFFFF00000000L
;
121 * Estimate of size cost to pay beyond payload in jvm for instance of byte [].
122 * Estimate based on study of jhat and jprofiler numbers.
124 // JHat says BU is 56 bytes.
125 // SizeOf which uses java.lang.instrument says 24 bytes. (3 longs?)
126 public static final int ESTIMATED_HEAP_TAX
= 16;
128 static final boolean UNSAFE_UNALIGNED
= HBasePlatformDependent
.unaligned();
131 * Returns length of the byte array, returning 0 if the array is null.
132 * Useful for calculating sizes.
133 * @param b byte array, which can be null
134 * @return 0 if b is null, otherwise returns length
136 final public static int len(byte[] b
) {
137 return b
== null ?
0 : b
.length
;
140 private byte[] bytes
;
145 * Create a zero-size sequence.
152 * Create a Bytes using the byte array as the initial value.
153 * @param bytes This array becomes the backing storage for the object.
155 public Bytes(byte[] bytes
) {
156 this(bytes
, 0, bytes
.length
);
160 * Set the new Bytes to the contents of the passed
162 * @param ibw the value to set this Bytes to.
164 public Bytes(final Bytes ibw
) {
165 this(ibw
.get(), ibw
.getOffset(), ibw
.getLength());
169 * Set the value to a given byte range
170 * @param bytes the new byte range to set to
171 * @param offset the offset in newData to start at
172 * @param length the number of bytes in the range
174 public Bytes(final byte[] bytes
, final int offset
,
177 this.offset
= offset
;
178 this.length
= length
;
182 * Get the data from the Bytes.
183 * @return The data is only valid between offset and offset+length.
185 public byte [] get() {
186 if (this.bytes
== null) {
187 throw new IllegalStateException("Uninitialiized. Null constructor " +
188 "called w/o accompaying readFields invocation");
194 * @param b Use passed bytes as backing array for this instance.
196 public void set(final byte [] b
) {
201 * @param b Use passed bytes as backing array for this instance.
205 public void set(final byte [] b
, final int offset
, final int length
) {
207 this.offset
= offset
;
208 this.length
= length
;
212 * @return the number of valid bytes in the buffer
214 public int getLength() {
215 if (this.bytes
== null) {
216 throw new IllegalStateException("Uninitialiized. Null constructor " +
217 "called w/o accompaying readFields invocation");
225 public int getOffset(){
230 public int hashCode() {
231 return Bytes
.hashCode(bytes
, offset
, length
);
235 * Define the sort order of the Bytes.
236 * @param that The other bytes writable
237 * @return Positive if left is bigger than right, 0 if they are equal, and
238 * negative if left is smaller than right.
241 public int compareTo(Bytes that
) {
242 return BYTES_RAWCOMPARATOR
.compare(
243 this.bytes
, this.offset
, this.length
,
244 that
.bytes
, that
.offset
, that
.length
);
248 * Compares the bytes in this object to the specified byte array
250 * @return Positive if left is bigger than right, 0 if they are equal, and
251 * negative if left is smaller than right.
253 public int compareTo(final byte [] that
) {
254 return BYTES_RAWCOMPARATOR
.compare(
255 this.bytes
, this.offset
, this.length
,
256 that
, 0, that
.length
);
260 * @see Object#equals(Object)
263 public boolean equals(Object right_obj
) {
264 if (right_obj
instanceof byte []) {
265 return compareTo((byte [])right_obj
) == 0;
267 if (right_obj
instanceof Bytes
) {
268 return compareTo((Bytes
)right_obj
) == 0;
274 * @see Object#toString()
277 public String
toString() {
278 return Bytes
.toString(bytes
, offset
, length
);
282 * @param array List of byte [].
283 * @return Array of byte [].
285 public static byte [][] toArray(final List
<byte []> array
) {
286 // List#toArray doesn't work on lists of byte [].
287 byte[][] results
= new byte[array
.size()][];
288 for (int i
= 0; i
< array
.size(); i
++) {
289 results
[i
] = array
.get(i
);
295 * Returns a copy of the bytes referred to by this writable
297 public byte[] copyBytes() {
298 return Arrays
.copyOfRange(bytes
, offset
, offset
+length
);
301 * Byte array comparator class.
303 @InterfaceAudience.Public
304 public static class ByteArrayComparator
implements RawComparator
<byte []> {
308 public ByteArrayComparator() {
312 public int compare(byte [] left
, byte [] right
) {
313 return compareTo(left
, right
);
316 public int compare(byte [] b1
, int s1
, int l1
, byte [] b2
, int s2
, int l2
) {
317 return LexicographicalComparerHolder
.BEST_COMPARER
.
318 compareTo(b1
, s1
, l1
, b2
, s2
, l2
);
323 * A {@link ByteArrayComparator} that treats the empty array as the largest value.
324 * This is useful for comparing row end keys for regions.
326 // TODO: unfortunately, HBase uses byte[0] as both start and end keys for region
327 // boundaries. Thus semantically, we should treat empty byte array as the smallest value
328 // while comparing row keys, start keys etc; but as the largest value for comparing
329 // region boundaries for endKeys.
330 @InterfaceAudience.Public
331 public static class RowEndKeyComparator
extends ByteArrayComparator
{
333 public int compare(byte[] left
, byte[] right
) {
334 return compare(left
, 0, left
.length
, right
, 0, right
.length
);
337 public int compare(byte[] b1
, int s1
, int l1
, byte[] b2
, int s2
, int l2
) {
338 if (b1
== b2
&& s1
== s2
&& l1
== l2
) {
342 return l2
; //0 or positive
347 return super.compare(b1
, s1
, l1
, b2
, s2
, l2
);
352 * Pass this to TreeMaps where byte [] are keys.
354 public final static Comparator
<byte []> BYTES_COMPARATOR
= new ByteArrayComparator();
357 * Use comparing byte arrays, byte-by-byte
359 public final static RawComparator
<byte []> BYTES_RAWCOMPARATOR
= new ByteArrayComparator();
362 * Read byte-array written with a WritableableUtils.vint prefix.
363 * @param in Input to read from.
364 * @return byte array read off <code>in</code>
365 * @throws IOException e
367 public static byte [] readByteArray(final DataInput in
)
369 int len
= WritableUtils
.readVInt(in
);
371 throw new NegativeArraySizeException(Integer
.toString(len
));
373 byte [] result
= new byte[len
];
374 in
.readFully(result
, 0, len
);
379 * Read byte-array written with a WritableableUtils.vint prefix.
380 * IOException is converted to a RuntimeException.
381 * @param in Input to read from.
382 * @return byte array read off <code>in</code>
384 public static byte [] readByteArrayThrowsRuntime(final DataInput in
) {
386 return readByteArray(in
);
387 } catch (Exception e
) {
388 throw new RuntimeException(e
);
393 * Write byte-array with a WritableableUtils.vint prefix.
394 * @param out output stream to be written to
395 * @param b array to write
396 * @throws IOException e
398 public static void writeByteArray(final DataOutput out
, final byte [] b
)
401 WritableUtils
.writeVInt(out
, 0);
403 writeByteArray(out
, b
, 0, b
.length
);
408 * Write byte-array to out with a vint length prefix.
409 * @param out output stream
411 * @param offset offset into array
412 * @param length length past offset
413 * @throws IOException e
415 public static void writeByteArray(final DataOutput out
, final byte [] b
,
416 final int offset
, final int length
)
418 WritableUtils
.writeVInt(out
, length
);
419 out
.write(b
, offset
, length
);
423 * Write byte-array from src to tgt with a vint length prefix.
424 * @param tgt target array
425 * @param tgtOffset offset into target array
426 * @param src source array
427 * @param srcOffset source offset
428 * @param srcLength source length
429 * @return New offset in src array.
431 public static int writeByteArray(final byte [] tgt
, final int tgtOffset
,
432 final byte [] src
, final int srcOffset
, final int srcLength
) {
433 byte [] vint
= vintToBytes(srcLength
);
434 System
.arraycopy(vint
, 0, tgt
, tgtOffset
, vint
.length
);
435 int offset
= tgtOffset
+ vint
.length
;
436 System
.arraycopy(src
, srcOffset
, tgt
, offset
, srcLength
);
437 return offset
+ srcLength
;
441 * Put bytes at the specified byte array position.
442 * @param tgtBytes the byte array
443 * @param tgtOffset position in the array
444 * @param srcBytes array to write out
445 * @param srcOffset source offset
446 * @param srcLength source length
447 * @return incremented offset
449 public static int putBytes(byte[] tgtBytes
, int tgtOffset
, byte[] srcBytes
,
450 int srcOffset
, int srcLength
) {
451 System
.arraycopy(srcBytes
, srcOffset
, tgtBytes
, tgtOffset
, srcLength
);
452 return tgtOffset
+ srcLength
;
456 * Write a single byte out to the specified byte array position.
457 * @param bytes the byte array
458 * @param offset position in the array
459 * @param b byte to write out
460 * @return incremented offset
462 public static int putByte(byte[] bytes
, int offset
, byte b
) {
468 * Add the whole content of the ByteBuffer to the bytes arrays. The ByteBuffer is modified.
469 * @param bytes the byte array
470 * @param offset position in the array
471 * @param buf ByteBuffer to write out
472 * @return incremented offset
474 public static int putByteBuffer(byte[] bytes
, int offset
, ByteBuffer buf
) {
475 int len
= buf
.remaining();
476 buf
.get(bytes
, offset
, len
);
481 * Returns a new byte array, copied from the given {@code buf},
482 * from the index 0 (inclusive) to the limit (exclusive),
483 * regardless of the current position.
484 * The position and the other index parameters are not changed.
486 * @param buf a byte buffer
487 * @return the byte array
488 * @see #getBytes(ByteBuffer)
490 public static byte[] toBytes(ByteBuffer buf
) {
491 ByteBuffer dup
= buf
.duplicate();
493 return readBytes(dup
);
496 private static byte[] readBytes(ByteBuffer buf
) {
497 byte [] result
= new byte[buf
.remaining()];
503 * @param b Presumed UTF-8 encoded byte array.
504 * @return String made from <code>b</code>
506 public static String
toString(final byte [] b
) {
510 return toString(b
, 0, b
.length
);
514 * Joins two byte arrays together using a separator.
515 * @param b1 The first byte array.
516 * @param sep The separator to use.
517 * @param b2 The second byte array.
519 public static String
toString(final byte [] b1
,
522 return toString(b1
, 0, b1
.length
) + sep
+ toString(b2
, 0, b2
.length
);
526 * This method will convert utf8 encoded bytes into a string. If
527 * the given byte array is null, this method will return null.
529 * @param b Presumed UTF-8 encoded byte array.
530 * @param off offset into array
531 * @return String made from <code>b</code> or null
533 public static String
toString(final byte[] b
, int off
) {
537 int len
= b
.length
- off
;
542 return new String(b
, off
, len
, UTF8_CSN
);
543 } catch (UnsupportedEncodingException e
) {
544 // should never happen!
545 throw new IllegalArgumentException("UTF8 encoding is not supported", e
);
550 * This method will convert utf8 encoded bytes into a string. If
551 * the given byte array is null, this method will return null.
553 * @param b Presumed UTF-8 encoded byte array.
554 * @param off offset into array
555 * @param len length of utf-8 sequence
556 * @return String made from <code>b</code> or null
558 public static String
toString(final byte[] b
, int off
, int len
) {
566 return new String(b
, off
, len
, UTF8_CSN
);
567 } catch (UnsupportedEncodingException e
) {
568 // should never happen!
569 throw new IllegalArgumentException("UTF8 encoding is not supported", e
);
574 * Write a printable representation of a byte array.
576 * @param b byte array
578 * @see #toStringBinary(byte[], int, int)
580 public static String
toStringBinary(final byte [] b
) {
583 return toStringBinary(b
, 0, b
.length
);
587 * Converts the given byte buffer to a printable representation,
588 * from the index 0 (inclusive) to the limit (exclusive),
589 * regardless of the current position.
590 * The position and the other index parameters are not changed.
592 * @param buf a byte buffer
593 * @return a string representation of the buffer's binary contents
594 * @see #toBytes(ByteBuffer)
595 * @see #getBytes(ByteBuffer)
597 public static String
toStringBinary(ByteBuffer buf
) {
600 if (buf
.hasArray()) {
601 return toStringBinary(buf
.array(), buf
.arrayOffset(), buf
.limit());
603 return toStringBinary(toBytes(buf
));
606 private static final char[] HEX_CHARS_UPPER
= {
607 '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'
611 * Write a printable representation of a byte array. Non-printable
612 * characters are hex escaped in the format \\x%02X, eg:
615 * @param b array to write out
616 * @param off offset to start at
617 * @param len length to write
618 * @return string output
620 public static String
toStringBinary(final byte [] b
, int off
, int len
) {
621 StringBuilder result
= new StringBuilder();
622 // Just in case we are passed a 'len' that is > buffer length...
623 if (off
>= b
.length
) return result
.toString();
624 if (off
+ len
> b
.length
) len
= b
.length
- off
;
625 for (int i
= off
; i
< off
+ len
; ++i
) {
626 int ch
= b
[i
] & 0xFF;
627 if (ch
>= ' ' && ch
<= '~' && ch
!= '\\') {
628 result
.append((char)ch
);
630 result
.append("\\x");
631 result
.append(HEX_CHARS_UPPER
[ch
/ 0x10]);
632 result
.append(HEX_CHARS_UPPER
[ch
% 0x10]);
635 return result
.toString();
638 private static boolean isHexDigit(char c
) {
640 (c
>= 'A' && c
<= 'F') ||
641 (c
>= '0' && c
<= '9');
645 * Takes a ASCII digit in the range A-F0-9 and returns
646 * the corresponding integer/ordinal value.
647 * @param ch The hex digit.
648 * @return The converted hex value as a byte.
650 public static byte toBinaryFromHex(byte ch
) {
651 if (ch
>= 'A' && ch
<= 'F')
652 return (byte) ((byte)10 + (byte) (ch
- 'A'));
654 return (byte) (ch
- '0');
657 public static byte [] toBytesBinary(String in
) {
658 // this may be bigger than we need, but let's be safe.
659 byte [] b
= new byte[in
.length()];
661 for (int i
= 0; i
< in
.length(); ++i
) {
662 char ch
= in
.charAt(i
);
663 if (ch
== '\\' && in
.length() > i
+1 && in
.charAt(i
+1) == 'x') {
664 // ok, take next 2 hex digits.
665 char hd1
= in
.charAt(i
+2);
666 char hd2
= in
.charAt(i
+3);
668 // they need to be A-F0-9:
669 if (!isHexDigit(hd1
) ||
671 // bogus escape code, ignore:
674 // turn hex ASCII digit -> number
675 byte d
= (byte) ((toBinaryFromHex((byte)hd1
) << 4) + toBinaryFromHex((byte)hd2
));
680 b
[size
++] = (byte) ch
;
684 byte [] b2
= new byte[size
];
685 System
.arraycopy(b
, 0, b2
, 0, size
);
690 * Converts a string to a UTF-8 byte array.
692 * @return the byte array
694 public static byte[] toBytes(String s
) {
696 return s
.getBytes(UTF8_CSN
);
697 } catch (UnsupportedEncodingException e
) {
698 // should never happen!
699 throw new IllegalArgumentException("UTF8 decoding is not supported", e
);
704 * Convert a boolean to a byte array. True becomes -1
705 * and false becomes 0.
708 * @return <code>b</code> encoded in a byte array.
710 public static byte [] toBytes(final boolean b
) {
711 return new byte[] { b ?
(byte) -1 : (byte) 0 };
715 * Reverses {@link #toBytes(boolean)}
717 * @return True or false.
719 public static boolean toBoolean(final byte [] b
) {
721 throw new IllegalArgumentException("Array has wrong size: " + b
.length
);
723 return b
[0] != (byte) 0;
727 * Convert a long value to a byte array using big-endian.
729 * @param val value to convert
730 * @return the byte array
732 public static byte[] toBytes(long val
) {
733 byte [] b
= new byte[8];
734 for (int i
= 7; i
> 0; i
--) {
743 * Converts a byte array to a long value. Reverses
744 * {@link #toBytes(long)}
746 * @return the long value
748 public static long toLong(byte[] bytes
) {
749 return toLong(bytes
, 0, SIZEOF_LONG
);
753 * Converts a byte array to a long value. Assumes there will be
754 * {@link #SIZEOF_LONG} bytes available.
757 * @param offset offset
758 * @return the long value
760 public static long toLong(byte[] bytes
, int offset
) {
761 return toLong(bytes
, offset
, SIZEOF_LONG
);
765 * Converts a byte array to a long value.
767 * @param bytes array of bytes
768 * @param offset offset into array
769 * @param length length of data (must be {@link #SIZEOF_LONG})
770 * @return the long value
771 * @throws IllegalArgumentException if length is not {@link #SIZEOF_LONG} or
772 * if there's not enough room in the array at the offset indicated.
774 public static long toLong(byte[] bytes
, int offset
, final int length
) {
775 if (length
!= SIZEOF_LONG
|| offset
+ length
> bytes
.length
) {
776 throw explainWrongLengthOrOffset(bytes
, offset
, length
, SIZEOF_LONG
);
778 return ConverterHolder
.BEST_CONVERTER
.toLong(bytes
, offset
, length
);
781 private static IllegalArgumentException
782 explainWrongLengthOrOffset(final byte[] bytes
,
785 final int expectedLength
) {
787 if (length
!= expectedLength
) {
788 reason
= "Wrong length: " + length
+ ", expected " + expectedLength
;
790 reason
= "offset (" + offset
+ ") + length (" + length
+ ") exceed the"
791 + " capacity of the array: " + bytes
.length
;
793 return new IllegalArgumentException(reason
);
797 * Put a long value out to the specified byte array position.
798 * @param bytes the byte array
799 * @param offset position in the array
800 * @param val long to write out
801 * @return incremented offset
802 * @throws IllegalArgumentException if the byte array given doesn't have
803 * enough room at the offset specified.
805 public static int putLong(byte[] bytes
, int offset
, long val
) {
806 if (bytes
.length
- offset
< SIZEOF_LONG
) {
807 throw new IllegalArgumentException("Not enough room to put a long at"
808 + " offset " + offset
+ " in a " + bytes
.length
+ " byte array");
810 return ConverterHolder
.BEST_CONVERTER
.putLong(bytes
, offset
, val
);
814 * Presumes float encoded as IEEE 754 floating-point "single format"
815 * @param bytes byte array
816 * @return Float made from passed byte array.
818 public static float toFloat(byte [] bytes
) {
819 return toFloat(bytes
, 0);
823 * Presumes float encoded as IEEE 754 floating-point "single format"
824 * @param bytes array to convert
825 * @param offset offset into array
826 * @return Float made from passed byte array.
828 public static float toFloat(byte [] bytes
, int offset
) {
829 return Float
.intBitsToFloat(toInt(bytes
, offset
, SIZEOF_INT
));
833 * @param bytes byte array
834 * @param offset offset to write to
835 * @param f float value
836 * @return New offset in <code>bytes</code>
838 public static int putFloat(byte [] bytes
, int offset
, float f
) {
839 return putInt(bytes
, offset
, Float
.floatToRawIntBits(f
));
843 * @param f float value
844 * @return the float represented as byte []
846 public static byte [] toBytes(final float f
) {
848 return Bytes
.toBytes(Float
.floatToRawIntBits(f
));
852 * @param bytes byte array
853 * @return Return double made from passed bytes.
855 public static double toDouble(final byte [] bytes
) {
856 return toDouble(bytes
, 0);
860 * @param bytes byte array
861 * @param offset offset where double is
862 * @return Return double made from passed bytes.
864 public static double toDouble(final byte [] bytes
, final int offset
) {
865 return Double
.longBitsToDouble(toLong(bytes
, offset
, SIZEOF_LONG
));
869 * @param bytes byte array
870 * @param offset offset to write to
872 * @return New offset into array <code>bytes</code>
874 public static int putDouble(byte [] bytes
, int offset
, double d
) {
875 return putLong(bytes
, offset
, Double
.doubleToLongBits(d
));
879 * Serialize a double as the IEEE 754 double format output. The resultant
880 * array will be 8 bytes long.
883 * @return the double represented as byte []
885 public static byte [] toBytes(final double d
) {
886 // Encode it as a long
887 return Bytes
.toBytes(Double
.doubleToRawLongBits(d
));
891 * Convert an int value to a byte array. Big-endian. Same as what DataOutputStream.writeInt
895 * @return the byte array
897 public static byte[] toBytes(int val
) {
898 byte [] b
= new byte[4];
899 for(int i
= 3; i
> 0; i
--) {
908 * Converts a byte array to an int value
909 * @param bytes byte array
910 * @return the int value
912 public static int toInt(byte[] bytes
) {
913 return toInt(bytes
, 0, SIZEOF_INT
);
917 * Converts a byte array to an int value
918 * @param bytes byte array
919 * @param offset offset into array
920 * @return the int value
922 public static int toInt(byte[] bytes
, int offset
) {
923 return toInt(bytes
, offset
, SIZEOF_INT
);
927 * Converts a byte array to an int value
928 * @param bytes byte array
929 * @param offset offset into array
930 * @param length length of int (has to be {@link #SIZEOF_INT})
931 * @return the int value
932 * @throws IllegalArgumentException if length is not {@link #SIZEOF_INT} or
933 * if there's not enough room in the array at the offset indicated.
935 public static int toInt(byte[] bytes
, int offset
, final int length
) {
936 if (length
!= SIZEOF_INT
|| offset
+ length
> bytes
.length
) {
937 throw explainWrongLengthOrOffset(bytes
, offset
, length
, SIZEOF_INT
);
939 return ConverterHolder
.BEST_CONVERTER
.toInt(bytes
, offset
, length
);
943 * Converts a byte array to an int value
944 * @param bytes byte array
945 * @param offset offset into array
946 * @param length how many bytes should be considered for creating int
947 * @return the int value
948 * @throws IllegalArgumentException if there's not enough room in the array at the offset
951 public static int readAsInt(byte[] bytes
, int offset
, final int length
) {
952 if (offset
+ length
> bytes
.length
) {
953 throw new IllegalArgumentException("offset (" + offset
+ ") + length (" + length
954 + ") exceed the" + " capacity of the array: " + bytes
.length
);
957 for(int i
= offset
; i
< (offset
+ length
); i
++) {
959 n ^
= bytes
[i
] & 0xFF;
965 * Put an int value out to the specified byte array position.
966 * @param bytes the byte array
967 * @param offset position in the array
968 * @param val int to write out
969 * @return incremented offset
970 * @throws IllegalArgumentException if the byte array given doesn't have
971 * enough room at the offset specified.
973 public static int putInt(byte[] bytes
, int offset
, int val
) {
974 if (bytes
.length
- offset
< SIZEOF_INT
) {
975 throw new IllegalArgumentException("Not enough room to put an int at"
976 + " offset " + offset
+ " in a " + bytes
.length
+ " byte array");
978 return ConverterHolder
.BEST_CONVERTER
.putInt(bytes
, offset
, val
);
982 * Convert a short value to a byte array of {@link #SIZEOF_SHORT} bytes long.
984 * @return the byte array
986 public static byte[] toBytes(short val
) {
987 byte[] b
= new byte[SIZEOF_SHORT
];
995 * Converts a byte array to a short value
996 * @param bytes byte array
997 * @return the short value
999 public static short toShort(byte[] bytes
) {
1000 return toShort(bytes
, 0, SIZEOF_SHORT
);
1004 * Converts a byte array to a short value
1005 * @param bytes byte array
1006 * @param offset offset into array
1007 * @return the short value
1009 public static short toShort(byte[] bytes
, int offset
) {
1010 return toShort(bytes
, offset
, SIZEOF_SHORT
);
1014 * Converts a byte array to a short value
1015 * @param bytes byte array
1016 * @param offset offset into array
1017 * @param length length, has to be {@link #SIZEOF_SHORT}
1018 * @return the short value
1019 * @throws IllegalArgumentException if length is not {@link #SIZEOF_SHORT}
1020 * or if there's not enough room in the array at the offset indicated.
1022 public static short toShort(byte[] bytes
, int offset
, final int length
) {
1023 if (length
!= SIZEOF_SHORT
|| offset
+ length
> bytes
.length
) {
1024 throw explainWrongLengthOrOffset(bytes
, offset
, length
, SIZEOF_SHORT
);
1026 return ConverterHolder
.BEST_CONVERTER
.toShort(bytes
, offset
, length
);
1030 * Returns a new byte array, copied from the given {@code buf},
1031 * from the position (inclusive) to the limit (exclusive).
1032 * The position and the other index parameters are not changed.
1034 * @param buf a byte buffer
1035 * @return the byte array
1036 * @see #toBytes(ByteBuffer)
1038 public static byte[] getBytes(ByteBuffer buf
) {
1039 return readBytes(buf
.duplicate());
1043 * Put a short value out to the specified byte array position.
1044 * @param bytes the byte array
1045 * @param offset position in the array
1046 * @param val short to write out
1047 * @return incremented offset
1048 * @throws IllegalArgumentException if the byte array given doesn't have
1049 * enough room at the offset specified.
1051 public static int putShort(byte[] bytes
, int offset
, short val
) {
1052 if (bytes
.length
- offset
< SIZEOF_SHORT
) {
1053 throw new IllegalArgumentException("Not enough room to put a short at"
1054 + " offset " + offset
+ " in a " + bytes
.length
+ " byte array");
1056 return ConverterHolder
.BEST_CONVERTER
.putShort(bytes
, offset
, val
);
1060 * Put an int value as short out to the specified byte array position. Only the lower 2 bytes of
1061 * the short will be put into the array. The caller of the API need to make sure they will not
1062 * loose the value by doing so. This is useful to store an unsigned short which is represented as
1063 * int in other parts.
1064 * @param bytes the byte array
1065 * @param offset position in the array
1066 * @param val value to write out
1067 * @return incremented offset
1068 * @throws IllegalArgumentException if the byte array given doesn't have
1069 * enough room at the offset specified.
1071 public static int putAsShort(byte[] bytes
, int offset
, int val
) {
1072 if (bytes
.length
- offset
< SIZEOF_SHORT
) {
1073 throw new IllegalArgumentException("Not enough room to put a short at"
1074 + " offset " + offset
+ " in a " + bytes
.length
+ " byte array");
1076 bytes
[offset
+1] = (byte) val
;
1078 bytes
[offset
] = (byte) val
;
1079 return offset
+ SIZEOF_SHORT
;
1083 * Convert a BigDecimal value to a byte array
1086 * @return the byte array
1088 public static byte[] toBytes(BigDecimal val
) {
1089 byte[] valueBytes
= val
.unscaledValue().toByteArray();
1090 byte[] result
= new byte[valueBytes
.length
+ SIZEOF_INT
];
1091 int offset
= putInt(result
, 0, val
.scale());
1092 putBytes(result
, offset
, valueBytes
, 0, valueBytes
.length
);
1098 * Converts a byte array to a BigDecimal
1101 * @return the char value
1103 public static BigDecimal
toBigDecimal(byte[] bytes
) {
1104 return toBigDecimal(bytes
, 0, bytes
.length
);
1108 * Converts a byte array to a BigDecimal value
1113 * @return the char value
1115 public static BigDecimal
toBigDecimal(byte[] bytes
, int offset
, final int length
) {
1116 if (bytes
== null || length
< SIZEOF_INT
+ 1 ||
1117 (offset
+ length
> bytes
.length
)) {
1121 int scale
= toInt(bytes
, offset
);
1122 byte[] tcBytes
= new byte[length
- SIZEOF_INT
];
1123 System
.arraycopy(bytes
, offset
+ SIZEOF_INT
, tcBytes
, 0, length
- SIZEOF_INT
);
1124 return new BigDecimal(new BigInteger(tcBytes
), scale
);
1128 * Put a BigDecimal value out to the specified byte array position.
1130 * @param bytes the byte array
1131 * @param offset position in the array
1132 * @param val BigDecimal to write out
1133 * @return incremented offset
1135 public static int putBigDecimal(byte[] bytes
, int offset
, BigDecimal val
) {
1136 if (bytes
== null) {
1140 byte[] valueBytes
= val
.unscaledValue().toByteArray();
1141 byte[] result
= new byte[valueBytes
.length
+ SIZEOF_INT
];
1142 offset
= putInt(result
, offset
, val
.scale());
1143 return putBytes(result
, offset
, valueBytes
, 0, valueBytes
.length
);
1147 * @param vint Integer to make a vint of.
1148 * @return Vint as bytes array.
1150 public static byte [] vintToBytes(final long vint
) {
1152 int size
= WritableUtils
.getVIntSize(i
);
1153 byte [] result
= new byte[size
];
1155 if (i
>= -112 && i
<= 127) {
1156 result
[offset
] = (byte) i
;
1162 i ^
= -1L; // take one's complement'
1172 result
[offset
++] = (byte) len
;
1174 len
= (len
< -120) ?
-(len
+ 120) : -(len
+ 112);
1176 for (int idx
= len
; idx
!= 0; idx
--) {
1177 int shiftbits
= (idx
- 1) * 8;
1178 long mask
= 0xFFL
<< shiftbits
;
1179 result
[offset
++] = (byte)((i
& mask
) >> shiftbits
);
1185 * @param buffer buffer to convert
1186 * @return vint bytes as an integer.
1188 public static long bytesToVint(final byte [] buffer
) {
1190 byte firstByte
= buffer
[offset
++];
1191 int len
= WritableUtils
.decodeVIntSize(firstByte
);
1196 for (int idx
= 0; idx
< len
-1; idx
++) {
1197 byte b
= buffer
[offset
++];
1201 return (WritableUtils
.isNegativeVInt(firstByte
) ? ~i
: i
);
1205 * Reads a zero-compressed encoded long from input buffer and returns it.
1206 * @param buffer Binary array
1207 * @param offset Offset into array at which vint begins.
1208 * @return deserialized long from buffer.
1210 public static long readAsVLong(final byte [] buffer
, final int offset
) {
1211 byte firstByte
= buffer
[offset
];
1212 int len
= WritableUtils
.decodeVIntSize(firstByte
);
1217 for (int idx
= 0; idx
< len
-1; idx
++) {
1218 byte b
= buffer
[offset
+ 1 + idx
];
1222 return (WritableUtils
.isNegativeVInt(firstByte
) ? ~i
: i
);
1226 * @param left left operand
1227 * @param right right operand
1228 * @return 0 if equal, < 0 if left is less than right, etc.
1230 public static int compareTo(final byte [] left
, final byte [] right
) {
1231 return LexicographicalComparerHolder
.BEST_COMPARER
.
1232 compareTo(left
, 0, left
== null?
0: left
.length
, right
, 0, right
== null?
0: right
.length
);
1236 * Lexicographically compare two arrays.
1238 * @param buffer1 left operand
1239 * @param buffer2 right operand
1240 * @param offset1 Where to start comparing in the left buffer
1241 * @param offset2 Where to start comparing in the right buffer
1242 * @param length1 How much to compare from the left buffer
1243 * @param length2 How much to compare from the right buffer
1244 * @return 0 if equal, < 0 if left is less than right, etc.
1246 public static int compareTo(byte[] buffer1
, int offset1
, int length1
,
1247 byte[] buffer2
, int offset2
, int length2
) {
1248 return LexicographicalComparerHolder
.BEST_COMPARER
.
1249 compareTo(buffer1
, offset1
, length1
, buffer2
, offset2
, length2
);
1252 interface Comparer
<T
> {
1254 T buffer1
, int offset1
, int length1
, T buffer2
, int offset2
, int length2
1258 static abstract class Converter
{
1259 abstract long toLong(byte[] bytes
, int offset
, int length
);
1260 abstract int putLong(byte[] bytes
, int offset
, long val
);
1262 abstract int toInt(byte[] bytes
, int offset
, final int length
);
1263 abstract int putInt(byte[] bytes
, int offset
, int val
);
1265 abstract short toShort(byte[] bytes
, int offset
, final int length
);
1266 abstract int putShort(byte[] bytes
, int offset
, short val
);
1270 static Comparer
<byte[]> lexicographicalComparerJavaImpl() {
1271 return LexicographicalComparerHolder
.PureJavaComparer
.INSTANCE
;
1274 static class ConverterHolder
{
1275 static final String UNSAFE_CONVERTER_NAME
=
1276 ConverterHolder
.class.getName() + "$UnsafeConverter";
1278 static final Converter BEST_CONVERTER
= getBestConverter();
1280 * Returns the Unsafe-using Converter, or falls back to the pure-Java
1281 * implementation if unable to do so.
1283 static Converter
getBestConverter() {
1285 Class
<?
> theClass
= Class
.forName(UNSAFE_CONVERTER_NAME
);
1287 // yes, UnsafeComparer does implement Comparer<byte[]>
1288 @SuppressWarnings("unchecked")
1289 Converter converter
= (Converter
) theClass
.getConstructor().newInstance();
1291 } catch (Throwable t
) { // ensure we really catch *everything*
1292 return PureJavaConverter
.INSTANCE
;
1296 protected static final class PureJavaConverter
extends Converter
{
1297 static final PureJavaConverter INSTANCE
= new PureJavaConverter();
1299 private PureJavaConverter() {}
1302 long toLong(byte[] bytes
, int offset
, int length
) {
1304 for(int i
= offset
; i
< offset
+ length
; i
++) {
1306 l ^
= bytes
[i
] & 0xFF;
1312 int putLong(byte[] bytes
, int offset
, long val
) {
1313 for(int i
= offset
+ 7; i
> offset
; i
--) {
1314 bytes
[i
] = (byte) val
;
1317 bytes
[offset
] = (byte) val
;
1318 return offset
+ SIZEOF_LONG
;
1322 int toInt(byte[] bytes
, int offset
, int length
) {
1324 for(int i
= offset
; i
< (offset
+ length
); i
++) {
1326 n ^
= bytes
[i
] & 0xFF;
1332 int putInt(byte[] bytes
, int offset
, int val
) {
1333 for(int i
= offset
+ 3; i
> offset
; i
--) {
1334 bytes
[i
] = (byte) val
;
1337 bytes
[offset
] = (byte) val
;
1338 return offset
+ SIZEOF_INT
;
1342 short toShort(byte[] bytes
, int offset
, int length
) {
1344 n
= (short) ((n ^ bytes
[offset
]) & 0xFF);
1345 n
= (short) (n
<< 8);
1346 n ^
= (short) (bytes
[offset
+1] & 0xFF);
1351 int putShort(byte[] bytes
, int offset
, short val
) {
1352 bytes
[offset
+1] = (byte) val
;
1354 bytes
[offset
] = (byte) val
;
1355 return offset
+ SIZEOF_SHORT
;
1359 protected static final class UnsafeConverter
extends Converter
{
1361 public UnsafeConverter() {}
1364 if (!UNSAFE_UNALIGNED
) {
1365 // It doesn't matter what we throw;
1366 // it's swallowed in getBestComparer().
1370 // sanity check - this should never fail
1371 if (HBasePlatformDependent
.arrayIndexScale(byte[].class) != 1) {
1372 throw new AssertionError();
1377 long toLong(byte[] bytes
, int offset
, int length
) {
1378 return UnsafeAccess
.toLong(bytes
, offset
);
1382 int putLong(byte[] bytes
, int offset
, long val
) {
1383 return UnsafeAccess
.putLong(bytes
, offset
, val
);
1387 int toInt(byte[] bytes
, int offset
, int length
) {
1388 return UnsafeAccess
.toInt(bytes
, offset
);
1392 int putInt(byte[] bytes
, int offset
, int val
) {
1393 return UnsafeAccess
.putInt(bytes
, offset
, val
);
1397 short toShort(byte[] bytes
, int offset
, int length
) {
1398 return UnsafeAccess
.toShort(bytes
, offset
);
1402 int putShort(byte[] bytes
, int offset
, short val
) {
1403 return UnsafeAccess
.putShort(bytes
, offset
, val
);
1409 * Provides a lexicographical comparer implementation; either a Java
1410 * implementation or a faster implementation based on {@code Unsafe}.
1412 * <p>Uses reflection to gracefully fall back to the Java implementation if
1413 * {@code Unsafe} isn't available.
1415 static class LexicographicalComparerHolder
{
1416 static final String UNSAFE_COMPARER_NAME
=
1417 LexicographicalComparerHolder
.class.getName() + "$UnsafeComparer";
1419 static final Comparer
<byte[]> BEST_COMPARER
= getBestComparer();
1421 * Returns the Unsafe-using Comparer, or falls back to the pure-Java
1422 * implementation if unable to do so.
1424 static Comparer
<byte[]> getBestComparer() {
1426 Class
<?
> theClass
= Class
.forName(UNSAFE_COMPARER_NAME
);
1428 // yes, UnsafeComparer does implement Comparer<byte[]>
1429 @SuppressWarnings("unchecked")
1430 Comparer
<byte[]> comparer
=
1431 (Comparer
<byte[]>) theClass
.getEnumConstants()[0];
1433 } catch (Throwable t
) { // ensure we really catch *everything*
1434 return lexicographicalComparerJavaImpl();
1438 enum PureJavaComparer
implements Comparer
<byte[]> {
1442 public int compareTo(byte[] buffer1
, int offset1
, int length1
,
1443 byte[] buffer2
, int offset2
, int length2
) {
1444 // Short circuit equal case
1445 if (buffer1
== buffer2
&&
1446 offset1
== offset2
&&
1447 length1
== length2
) {
1450 // Bring WritableComparator code local
1451 int end1
= offset1
+ length1
;
1452 int end2
= offset2
+ length2
;
1453 for (int i
= offset1
, j
= offset2
; i
< end1
&& j
< end2
; i
++, j
++) {
1454 int a
= (buffer1
[i
] & 0xff);
1455 int b
= (buffer2
[j
] & 0xff);
1460 return length1
- length2
;
1464 enum UnsafeComparer
implements Comparer
<byte[]> {
1468 if (!UNSAFE_UNALIGNED
) {
1469 // It doesn't matter what we throw;
1470 // it's swallowed in getBestComparer().
1474 // sanity check - this should never fail
1475 if (HBasePlatformDependent
.arrayIndexScale(byte[].class) != 1) {
1476 throw new AssertionError();
1481 * Lexicographically compare two arrays.
1483 * @param buffer1 left operand
1484 * @param buffer2 right operand
1485 * @param offset1 Where to start comparing in the left buffer
1486 * @param offset2 Where to start comparing in the right buffer
1487 * @param length1 How much to compare from the left buffer
1488 * @param length2 How much to compare from the right buffer
1489 * @return 0 if equal, < 0 if left is less than right, etc.
1492 public int compareTo(byte[] buffer1
, int offset1
, int length1
,
1493 byte[] buffer2
, int offset2
, int length2
) {
1495 // Short circuit equal case
1496 if (buffer1
== buffer2
&&
1497 offset1
== offset2
&&
1498 length1
== length2
) {
1501 final int stride
= 8;
1502 final int minLength
= Math
.min(length1
, length2
);
1503 int strideLimit
= minLength
& ~
(stride
- 1);
1504 final long offset1Adj
= offset1
+ UnsafeAccess
.BYTE_ARRAY_BASE_OFFSET
;
1505 final long offset2Adj
= offset2
+ UnsafeAccess
.BYTE_ARRAY_BASE_OFFSET
;
1509 * Compare 8 bytes at a time. Benchmarking on x86 shows a stride of 8 bytes is no slower
1510 * than 4 bytes even on 32-bit. On the other hand, it is substantially faster on 64-bit.
1512 for (i
= 0; i
< strideLimit
; i
+= stride
) {
1513 long lw
= HBasePlatformDependent
.getLong(buffer1
, offset1Adj
+ i
);
1514 long rw
= HBasePlatformDependent
.getLong(buffer2
, offset2Adj
+ i
);
1516 if(!UnsafeAccess
.LITTLE_ENDIAN
) {
1517 return ((lw
+ Long
.MIN_VALUE
) < (rw
+ Long
.MIN_VALUE
)) ?
-1 : 1;
1521 * We want to compare only the first index where left[index] != right[index]. This
1522 * corresponds to the least significant nonzero byte in lw ^ rw, since lw and rw are
1523 * little-endian. Long.numberOfTrailingZeros(diff) tells us the least significant
1524 * nonzero bit, and zeroing out the first three bits of L.nTZ gives us the shift to get
1525 * that least significant nonzero byte. This comparison logic is based on UnsignedBytes
1526 * comparator from guava v21
1528 int n
= Long
.numberOfTrailingZeros(lw ^ rw
) & ~
0x7;
1529 return ((int) ((lw
>>> n
) & 0xFF)) - ((int) ((rw
>>> n
) & 0xFF));
1533 // The epilogue to cover the last (minLength % stride) elements.
1534 for (; i
< minLength
; i
++) {
1535 int a
= (buffer1
[offset1
+ i
] & 0xFF);
1536 int b
= (buffer2
[offset2
+ i
] & 0xFF);
1541 return length1
- length2
;
1547 * @param left left operand
1548 * @param right right operand
1549 * @return True if equal
1551 public static boolean equals(final byte [] left
, final byte [] right
) {
1552 // Could use Arrays.equals?
1553 //noinspection SimplifiableConditionalExpression
1554 if (left
== right
) return true;
1555 if (left
== null || right
== null) return false;
1556 if (left
.length
!= right
.length
) return false;
1557 if (left
.length
== 0) return true;
1559 // Since we're often comparing adjacent sorted data,
1560 // it's usual to have equal arrays except for the very last byte
1561 // so check that first
1562 if (left
[left
.length
- 1] != right
[right
.length
- 1]) return false;
1564 return compareTo(left
, right
) == 0;
1567 public static boolean equals(final byte[] left
, int leftOffset
, int leftLen
,
1568 final byte[] right
, int rightOffset
, int rightLen
) {
1569 // short circuit case
1570 if (left
== right
&&
1571 leftOffset
== rightOffset
&&
1572 leftLen
== rightLen
) {
1575 // different lengths fast check
1576 if (leftLen
!= rightLen
) {
1583 // Since we're often comparing adjacent sorted data,
1584 // it's usual to have equal arrays except for the very last byte
1585 // so check that first
1586 if (left
[leftOffset
+ leftLen
- 1] != right
[rightOffset
+ rightLen
- 1]) return false;
1588 return LexicographicalComparerHolder
.BEST_COMPARER
.
1589 compareTo(left
, leftOffset
, leftLen
, right
, rightOffset
, rightLen
) == 0;
1594 * @param a left operand
1595 * @param buf right operand
1596 * @return True if equal
1598 public static boolean equals(byte[] a
, ByteBuffer buf
) {
1599 if (a
== null) return buf
== null;
1600 if (buf
== null) return false;
1601 if (a
.length
!= buf
.remaining()) return false;
1603 // Thou shalt not modify the original byte buffer in what should be read only operations.
1604 ByteBuffer b
= buf
.duplicate();
1605 for (byte anA
: a
) {
1606 if (anA
!= b
.get()) {
1615 * Return true if the byte array on the right is a prefix of the byte
1616 * array on the left.
1618 public static boolean startsWith(byte[] bytes
, byte[] prefix
) {
1619 return bytes
!= null && prefix
!= null &&
1620 bytes
.length
>= prefix
.length
&&
1621 LexicographicalComparerHolder
.BEST_COMPARER
.
1622 compareTo(bytes
, 0, prefix
.length
, prefix
, 0, prefix
.length
) == 0;
1626 * @param b bytes to hash
1627 * @return Runs {@link WritableComparator#hashBytes(byte[], int)} on the
1628 * passed in array. This method is what {@link org.apache.hadoop.io.Text}
1629 * use calculating hash code.
1631 public static int hashCode(final byte [] b
) {
1632 return hashCode(b
, b
.length
);
1637 * @param length length of the value
1638 * @return Runs {@link WritableComparator#hashBytes(byte[], int)} on the
1639 * passed in array. This method is what {@link org.apache.hadoop.io.Text}
1640 * use calculating hash code.
1642 public static int hashCode(final byte [] b
, final int length
) {
1643 return WritableComparator
.hashBytes(b
, length
);
1647 * @param b bytes to hash
1648 * @return A hash of <code>b</code> as an Integer that can be used as key in
1651 public static Integer
mapKey(final byte [] b
) {
1656 * @param b bytes to hash
1657 * @param length length to hash
1658 * @return A hash of <code>b</code> as an Integer that can be used as key in
1661 public static Integer
mapKey(final byte [] b
, final int length
) {
1662 return hashCode(b
, length
);
1666 * @param a lower half
1667 * @param b upper half
1668 * @return New array that has a in lower half and b in upper half.
1670 public static byte [] add(final byte [] a
, final byte [] b
) {
1671 return add(a
, b
, EMPTY_BYTE_ARRAY
);
1675 * @param a first third
1676 * @param b second third
1677 * @param c third third
1678 * @return New array made from a, b and c
1680 public static byte [] add(final byte [] a
, final byte [] b
, final byte [] c
) {
1681 byte [] result
= new byte[a
.length
+ b
.length
+ c
.length
];
1682 System
.arraycopy(a
, 0, result
, 0, a
.length
);
1683 System
.arraycopy(b
, 0, result
, a
.length
, b
.length
);
1684 System
.arraycopy(c
, 0, result
, a
.length
+ b
.length
, c
.length
);
1689 * @param arrays all the arrays to concatenate together.
1690 * @return New array made from the concatenation of the given arrays.
1692 public static byte [] add(final byte [][] arrays
) {
1694 for (int i
= 0; i
< arrays
.length
; i
++) {
1695 length
+= arrays
[i
].length
;
1697 byte [] result
= new byte[length
];
1699 for (int i
= 0; i
< arrays
.length
; i
++) {
1700 System
.arraycopy(arrays
[i
], 0, result
, index
, arrays
[i
].length
);
1701 index
+= arrays
[i
].length
;
1708 * @param length amount of bytes to grab
1709 * @return First <code>length</code> bytes from <code>a</code>
1711 public static byte [] head(final byte [] a
, final int length
) {
1712 if (a
.length
< length
) {
1715 byte [] result
= new byte[length
];
1716 System
.arraycopy(a
, 0, result
, 0, length
);
1722 * @param length amount of bytes to snarf
1723 * @return Last <code>length</code> bytes from <code>a</code>
1725 public static byte [] tail(final byte [] a
, final int length
) {
1726 if (a
.length
< length
) {
1729 byte [] result
= new byte[length
];
1730 System
.arraycopy(a
, a
.length
- length
, result
, 0, length
);
1736 * @param length new array size
1737 * @return Value in <code>a</code> plus <code>length</code> prepended 0 bytes
1739 public static byte [] padHead(final byte [] a
, final int length
) {
1740 byte [] padding
= new byte[length
];
1741 for (int i
= 0; i
< length
; i
++) {
1744 return add(padding
,a
);
1749 * @param length new array size
1750 * @return Value in <code>a</code> plus <code>length</code> appended 0 bytes
1752 public static byte [] padTail(final byte [] a
, final int length
) {
1753 byte [] padding
= new byte[length
];
1754 for (int i
= 0; i
< length
; i
++) {
1757 return add(a
,padding
);
1761 * Split passed range. Expensive operation relatively. Uses BigInteger math.
1762 * Useful splitting ranges for MapReduce jobs.
1763 * @param a Beginning of range
1764 * @param b End of range
1765 * @param num Number of times to split range. Pass 1 if you want to split
1766 * the range in two; i.e. one split.
1767 * @return Array of dividing values
1769 public static byte [][] split(final byte [] a
, final byte [] b
, final int num
) {
1770 return split(a
, b
, false, num
);
1774 * Split passed range. Expensive operation relatively. Uses BigInteger math.
1775 * Useful splitting ranges for MapReduce jobs.
1776 * @param a Beginning of range
1777 * @param b End of range
1778 * @param inclusive Whether the end of range is prefix-inclusive or is
1779 * considered an exclusive boundary. Automatic splits are generally exclusive
1780 * and manual splits with an explicit range utilize an inclusive end of range.
1781 * @param num Number of times to split range. Pass 1 if you want to split
1782 * the range in two; i.e. one split.
1783 * @return Array of dividing values
1785 public static byte[][] split(final byte[] a
, final byte[] b
,
1786 boolean inclusive
, final int num
) {
1787 byte[][] ret
= new byte[num
+ 2][];
1789 Iterable
<byte[]> iter
= iterateOnSplits(a
, b
, inclusive
, num
);
1792 for (byte[] elem
: iter
) {
1799 * Iterate over keys within the passed range, splitting at an [a,b) boundary.
1801 public static Iterable
<byte[]> iterateOnSplits(final byte[] a
,
1802 final byte[] b
, final int num
)
1804 return iterateOnSplits(a
, b
, false, num
);
1808 * Iterate over keys within the passed range.
1810 public static Iterable
<byte[]> iterateOnSplits(
1811 final byte[] a
, final byte[]b
, boolean inclusive
, final int num
)
1815 if (a
.length
< b
.length
) {
1816 aPadded
= padTail(a
, b
.length
- a
.length
);
1818 } else if (b
.length
< a
.length
) {
1820 bPadded
= padTail(b
, a
.length
- b
.length
);
1825 if (compareTo(aPadded
,bPadded
) >= 0) {
1826 throw new IllegalArgumentException("b <= a");
1829 throw new IllegalArgumentException("num cannot be <= 0");
1831 byte [] prependHeader
= {1, 0};
1832 final BigInteger startBI
= new BigInteger(add(prependHeader
, aPadded
));
1833 final BigInteger stopBI
= new BigInteger(add(prependHeader
, bPadded
));
1834 BigInteger diffBI
= stopBI
.subtract(startBI
);
1836 diffBI
= diffBI
.add(BigInteger
.ONE
);
1838 final BigInteger splitsBI
= BigInteger
.valueOf(num
+ 1);
1839 //when diffBI < splitBI, use an additional byte to increase diffBI
1840 if(diffBI
.compareTo(splitsBI
) < 0) {
1841 byte[] aPaddedAdditional
= new byte[aPadded
.length
+1];
1842 byte[] bPaddedAdditional
= new byte[bPadded
.length
+1];
1843 for (int i
= 0; i
< aPadded
.length
; i
++){
1844 aPaddedAdditional
[i
] = aPadded
[i
];
1846 for (int j
= 0; j
< bPadded
.length
; j
++){
1847 bPaddedAdditional
[j
] = bPadded
[j
];
1849 aPaddedAdditional
[aPadded
.length
] = 0;
1850 bPaddedAdditional
[bPadded
.length
] = 0;
1851 return iterateOnSplits(aPaddedAdditional
, bPaddedAdditional
, inclusive
, num
);
1853 final BigInteger intervalBI
;
1855 intervalBI
= diffBI
.divide(splitsBI
);
1856 } catch(Exception e
) {
1857 LOG
.error("Exception caught during division", e
);
1861 final Iterator
<byte[]> iterator
= new Iterator
<byte[]>() {
1865 public boolean hasNext() {
1870 public byte[] next() {
1872 if (i
== 0) return a
;
1873 if (i
== num
+ 1) return b
;
1875 BigInteger curBI
= startBI
.add(intervalBI
.multiply(BigInteger
.valueOf(i
)));
1876 byte [] padded
= curBI
.toByteArray();
1878 padded
= tail(padded
, padded
.length
- 2);
1880 padded
= tail(padded
, padded
.length
- 1);
1885 public void remove() {
1886 throw new UnsupportedOperationException();
1891 return new Iterable
<byte[]>() {
1893 public Iterator
<byte[]> iterator() {
1900 * @param bytes array to hash
1901 * @param offset offset to start from
1902 * @param length length to hash
1904 public static int hashCode(byte[] bytes
, int offset
, int length
) {
1906 for (int i
= offset
; i
< offset
+ length
; i
++)
1907 hash
= (31 * hash
) + bytes
[i
];
1913 * @return Array of byte arrays made from passed array of Text
1915 public static byte [][] toByteArrays(final String
[] t
) {
1916 byte [][] result
= new byte[t
.length
][];
1917 for (int i
= 0; i
< t
.length
; i
++) {
1918 result
[i
] = Bytes
.toBytes(t
[i
]);
1925 * @return Array of binary byte arrays made from passed array of binary strings
1927 public static byte[][] toBinaryByteArrays(final String
[] t
) {
1928 byte[][] result
= new byte[t
.length
][];
1929 for (int i
= 0; i
< t
.length
; i
++) {
1930 result
[i
] = Bytes
.toBytesBinary(t
[i
]);
1936 * @param column operand
1937 * @return A byte array of a byte array where first and only entry is
1938 * <code>column</code>
1940 public static byte [][] toByteArrays(final String column
) {
1941 return toByteArrays(toBytes(column
));
1945 * @param column operand
1946 * @return A byte array of a byte array where first and only entry is
1947 * <code>column</code>
1949 public static byte [][] toByteArrays(final byte [] column
) {
1950 byte [][] result
= new byte[1][];
1956 * Binary search for keys in indexes using Bytes.BYTES_RAWCOMPARATOR.
1958 * @param arr array of byte arrays to search for
1959 * @param key the key you want to find
1960 * @param offset the offset in the key you want to find
1961 * @param length the length of the key
1962 * @return zero-based index of the key, if the key is present in the array.
1963 * Otherwise, a value -(i + 1) such that the key is between arr[i -
1964 * 1] and arr[i] non-inclusively, where i is in [0, i], if we define
1965 * arr[-1] = -Inf and arr[N] = Inf for an N-element array. The above
1966 * means that this function can return 2N + 1 different values
1967 * ranging from -(N + 1) to N - 1.
1969 public static int binarySearch(byte[][] arr
, byte[] key
, int offset
, int length
) {
1971 int high
= arr
.length
- 1;
1973 while (low
<= high
) {
1974 int mid
= low
+ ((high
- low
) >> 1);
1975 // we have to compare in this order, because the comparator order
1976 // has special logic when the 'left side' is a special key.
1977 int cmp
= Bytes
.BYTES_RAWCOMPARATOR
1978 .compare(key
, offset
, length
, arr
[mid
], 0, arr
[mid
].length
);
1979 // key lives above the midpoint
1982 // key lives below the midpoint
1985 // BAM. how often does this really happen?
1993 * Binary search for keys in indexes.
1995 * @param arr array of byte arrays to search for
1996 * @param key the key you want to find
1997 * @param comparator a comparator to compare.
1998 * @return zero-based index of the key, if the key is present in the array.
1999 * Otherwise, a value -(i + 1) such that the key is between arr[i -
2000 * 1] and arr[i] non-inclusively, where i is in [0, i], if we define
2001 * arr[-1] = -Inf and arr[N] = Inf for an N-element array. The above
2002 * means that this function can return 2N + 1 different values
2003 * ranging from -(N + 1) to N - 1.
2004 * @return the index of the block
2006 public static int binarySearch(Cell
[] arr
, Cell key
, CellComparator comparator
) {
2008 int high
= arr
.length
- 1;
2009 while (low
<= high
) {
2010 int mid
= low
+ ((high
- low
) >> 1);
2011 // we have to compare in this order, because the comparator order
2012 // has special logic when the 'left side' is a special key.
2013 int cmp
= comparator
.compare(key
, arr
[mid
]);
2014 // key lives above the midpoint
2017 // key lives below the midpoint
2020 // BAM. how often does this really happen?
2028 * Bytewise binary increment/deincrement of long contained in byte array
2031 * @param value - array of bytes containing long (length <= SIZEOF_LONG)
2032 * @param amount value will be incremented on (deincremented if negative)
2033 * @return array of bytes containing incremented long (length == SIZEOF_LONG)
2035 public static byte [] incrementBytes(byte[] value
, long amount
)
2038 if (val
.length
< SIZEOF_LONG
) {
2039 // Hopefully this doesn't happen too often.
2042 newvalue
= new byte[]{-1, -1, -1, -1, -1, -1, -1, -1};
2044 newvalue
= new byte[SIZEOF_LONG
];
2046 System
.arraycopy(val
, 0, newvalue
, newvalue
.length
- val
.length
,
2049 } else if (val
.length
> SIZEOF_LONG
) {
2050 throw new IllegalArgumentException("Increment Bytes - value too big: " +
2053 if(amount
== 0) return val
;
2055 return binaryIncrementNeg(val
, amount
);
2057 return binaryIncrementPos(val
, amount
);
2060 /* increment/deincrement for positive value */
2061 private static byte [] binaryIncrementPos(byte [] value
, long amount
) {
2068 for(int i
=0;i
<value
.length
;i
++) {
2069 int cur
= ((int)amo
% 256) * sign
;
2071 int val
= value
[value
.length
-i
-1] & 0x0ff;
2072 int total
= val
+ cur
;
2076 } else if (total
< 0) {
2079 value
[value
.length
-i
-1] = (byte)total
;
2080 if (amo
== 0) return value
;
2085 /* increment/deincrement for negative value */
2086 private static byte [] binaryIncrementNeg(byte [] value
, long amount
) {
2093 for(int i
=0;i
<value
.length
;i
++) {
2094 int cur
= ((int)amo
% 256) * sign
;
2096 int val
= ((~value
[value
.length
-i
-1]) & 0x0ff) + 1;
2097 int total
= cur
- val
;
2100 } else if (total
< -256) {
2104 value
[value
.length
-i
-1] = (byte)total
;
2105 if (amo
== 0) return value
;
2111 * Writes a string as a fixed-size field, padded with zeros.
2113 public static void writeStringFixedSize(final DataOutput out
, String s
,
2114 int size
) throws IOException
{
2115 byte[] b
= toBytes(s
);
2116 if (b
.length
> size
) {
2117 throw new IOException("Trying to write " + b
.length
+ " bytes (" +
2118 toStringBinary(b
) + ") into a field of length " + size
);
2122 for (int i
= 0; i
< size
- s
.length(); ++i
)
2127 * Reads a fixed-size field and interprets it as a string padded with zeros.
2129 public static String
readStringFixedSize(final DataInput in
, int size
)
2130 throws IOException
{
2131 byte[] b
= new byte[size
];
2134 while (n
> 0 && b
[n
- 1] == 0)
2137 return toString(b
, 0, n
);
2141 * Copy the byte array given in parameter and return an instance
2142 * of a new byte array with the same length and the same content.
2143 * @param bytes the byte array to duplicate
2144 * @return a copy of the given byte array
2146 public static byte [] copy(byte [] bytes
) {
2147 if (bytes
== null) return null;
2148 byte [] result
= new byte[bytes
.length
];
2149 System
.arraycopy(bytes
, 0, result
, 0, bytes
.length
);
2154 * Copy the byte array given in parameter and return an instance
2155 * of a new byte array with the same length and the same content.
2156 * @param bytes the byte array to copy from
2157 * @return a copy of the given designated byte array
2161 public static byte [] copy(byte [] bytes
, final int offset
, final int length
) {
2162 if (bytes
== null) return null;
2163 byte [] result
= new byte[length
];
2164 System
.arraycopy(bytes
, offset
, result
, 0, length
);
2169 * Search sorted array "a" for byte "key". I can't remember if I wrote this or copied it from
2170 * somewhere. (mcorgan)
2171 * @param a Array to search. Entries must be sorted and unique.
2172 * @param fromIndex First index inclusive of "a" to include in the search.
2173 * @param toIndex Last index exclusive of "a" to include in the search.
2174 * @param key The byte to search for.
2175 * @return The index of key if found. If not found, return -(index + 1), where negative indicates
2176 * "not found" and the "index + 1" handles the "-0" case.
2178 public static int unsignedBinarySearch(byte[] a
, int fromIndex
, int toIndex
, byte key
) {
2179 int unsignedKey
= key
& 0xff;
2180 int low
= fromIndex
;
2181 int high
= toIndex
- 1;
2183 while (low
<= high
) {
2184 int mid
= low
+ ((high
- low
) >> 1);
2185 int midVal
= a
[mid
] & 0xff;
2187 if (midVal
< unsignedKey
) {
2189 } else if (midVal
> unsignedKey
) {
2192 return mid
; // key found
2195 return -(low
+ 1); // key not found.
2199 * Treat the byte[] as an unsigned series of bytes, most significant bits first. Start by adding
2200 * 1 to the rightmost bit/byte and carry over all overflows to the more significant bits/bytes.
2202 * @param input The byte[] to increment.
2203 * @return The incremented copy of "in". May be same length or 1 byte longer.
2205 public static byte[] unsignedCopyAndIncrement(final byte[] input
) {
2206 byte[] copy
= copy(input
);
2208 throw new IllegalArgumentException("cannot increment null array");
2210 for (int i
= copy
.length
- 1; i
>= 0; --i
) {
2211 if (copy
[i
] == -1) {// -1 is all 1-bits, which is the unsigned maximum
2218 // we maxed out the array
2219 byte[] out
= new byte[copy
.length
+ 1];
2221 System
.arraycopy(copy
, 0, out
, 1, copy
.length
);
2225 public static boolean equals(List
<byte[]> a
, List
<byte[]> b
) {
2235 if (a
.size() != b
.size()) {
2238 for (int i
= 0; i
< a
.size(); ++i
) {
2239 if (!Bytes
.equals(a
.get(i
), b
.get(i
))) {
2246 public static boolean isSorted(Collection
<byte[]> arrays
) {
2247 if (!CollectionUtils
.isEmpty(arrays
)) {
2248 byte[] previous
= new byte[0];
2249 for (byte[] array
: arrays
) {
2250 if (Bytes
.compareTo(previous
, array
) > 0) {
2259 public static List
<byte[]> getUtf8ByteArrays(List
<String
> strings
) {
2260 if (CollectionUtils
.isEmpty(strings
)) {
2261 return Collections
.emptyList();
2263 List
<byte[]> byteArrays
= new ArrayList
<>(strings
.size());
2264 strings
.forEach(s
-> byteArrays
.add(Bytes
.toBytes(s
)));
2269 * Returns the index of the first appearance of the value {@code target} in
2272 * @param array an array of {@code byte} values, possibly empty
2273 * @param target a primitive {@code byte} value
2274 * @return the least index {@code i} for which {@code array[i] == target}, or
2275 * {@code -1} if no such index exists.
2277 public static int indexOf(byte[] array
, byte target
) {
2278 for (int i
= 0; i
< array
.length
; i
++) {
2279 if (array
[i
] == target
) {
2287 * Returns the start position of the first occurrence of the specified {@code
2288 * target} within {@code array}, or {@code -1} if there is no such occurrence.
2290 * <p>More formally, returns the lowest index {@code i} such that {@code
2291 * java.util.Arrays.copyOfRange(array, i, i + target.length)} contains exactly
2292 * the same elements as {@code target}.
2294 * @param array the array to search for the sequence {@code target}
2295 * @param target the array to search for as a sub-sequence of {@code array}
2297 public static int indexOf(byte[] array
, byte[] target
) {
2298 checkNotNull(array
, "array");
2299 checkNotNull(target
, "target");
2300 if (target
.length
== 0) {
2305 for (int i
= 0; i
< array
.length
- target
.length
+ 1; i
++) {
2306 for (int j
= 0; j
< target
.length
; j
++) {
2307 if (array
[i
+ j
] != target
[j
]) {
2317 * @param array an array of {@code byte} values, possibly empty
2318 * @param target a primitive {@code byte} value
2319 * @return {@code true} if {@code target} is present as an element anywhere in {@code array}.
2321 public static boolean contains(byte[] array
, byte target
) {
2322 return indexOf(array
, target
) > -1;
2326 * @param array an array of {@code byte} values, possibly empty
2327 * @param target an array of {@code byte}
2328 * @return {@code true} if {@code target} is present anywhere in {@code array}
2330 public static boolean contains(byte[] array
, byte[] target
) {
2331 return indexOf(array
, target
) > -1;
2335 * Fill given array with zeros.
2336 * @param b array which needs to be filled with zeros
2338 public static void zero(byte[] b
) {
2339 zero(b
, 0, b
.length
);
2343 * Fill given array with zeros at the specified position.
2348 public static void zero(byte[] b
, int offset
, int length
) {
2349 checkPositionIndex(offset
, b
.length
, "offset");
2350 checkArgument(length
> 0, "length must be greater than 0");
2351 checkPositionIndex(offset
+ length
, b
.length
, "offset + length");
2352 Arrays
.fill(b
, offset
, offset
+ length
, (byte) 0);
2355 // Pseudorandom random number generator, do not use SecureRandom here
2356 private static final Random RNG
= new Random();
2359 * Fill given array with random bytes.
2360 * @param b array which needs to be filled with random bytes
2362 * If you want random bytes generated by a strong source of randomness use {@link
2363 * Bytes#secureRandom(byte[])}.
2364 * @param b array which needs to be filled with random bytes
2366 public static void random(byte[] b
) {
2371 * Fill given array with random bytes at the specified position.
2373 * If you want random bytes generated by a strong source of randomness use {@link
2374 * Bytes#secureRandom(byte[], int, int)}.
2375 * @param b array which needs to be filled with random bytes
2376 * @param offset staring offset in array
2377 * @param length number of bytes to fill
2379 public static void random(byte[] b
, int offset
, int length
) {
2380 checkPositionIndex(offset
, b
.length
, "offset");
2381 checkArgument(length
> 0, "length must be greater than 0");
2382 checkPositionIndex(offset
+ length
, b
.length
, "offset + length");
2383 byte[] buf
= new byte[length
];
2385 System
.arraycopy(buf
, 0, b
, offset
, length
);
2388 // Bytes.secureRandom may be used to create key material.
2389 private static final SecureRandom SECURE_RNG
= new SecureRandom();
2392 * Fill given array with random bytes using a strong random number generator.
2393 * @param b array which needs to be filled with random bytes
2395 public static void secureRandom(byte[] b
) {
2396 SECURE_RNG
.nextBytes(b
);
2400 * Fill given array with random bytes at the specified position using a strong random number
2402 * @param b array which needs to be filled with random bytes
2403 * @param offset staring offset in array
2404 * @param length number of bytes to fill
2406 public static void secureRandom(byte[] b
, int offset
, int length
) {
2407 checkPositionIndex(offset
, b
.length
, "offset");
2408 checkArgument(length
> 0, "length must be greater than 0");
2409 checkPositionIndex(offset
+ length
, b
.length
, "offset + length");
2410 byte[] buf
= new byte[length
];
2411 SECURE_RNG
.nextBytes(buf
);
2412 System
.arraycopy(buf
, 0, b
, offset
, length
);
2416 * Create a max byte array with the specified max byte count
2417 * @param maxByteCount the length of returned byte array
2418 * @return the created max byte array
2420 public static byte[] createMaxByteArray(int maxByteCount
) {
2421 byte[] maxByteArray
= new byte[maxByteCount
];
2422 for (int i
= 0; i
< maxByteArray
.length
; i
++) {
2423 maxByteArray
[i
] = (byte) 0xff;
2425 return maxByteArray
;
2429 * Create a byte array which is multiple given bytes
2432 * @return byte array
2434 public static byte[] multiple(byte[] srcBytes
, int multiNum
) {
2435 if (multiNum
<= 0) {
2438 byte[] result
= new byte[srcBytes
.length
* multiNum
];
2439 for (int i
= 0; i
< multiNum
; i
++) {
2440 System
.arraycopy(srcBytes
, 0, result
, i
* srcBytes
.length
,
2446 private static final char[] HEX_CHARS
= {
2447 '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'
2451 * Convert a byte range into a hex string
2453 public static String
toHex(byte[] b
, int offset
, int length
) {
2454 checkArgument(length
<= Integer
.MAX_VALUE
/ 2);
2455 int numChars
= length
* 2;
2456 char[] ch
= new char[numChars
];
2457 for (int i
= 0; i
< numChars
; i
+= 2)
2459 byte d
= b
[offset
+ i
/2];
2460 ch
[i
] = HEX_CHARS
[(d
>> 4) & 0x0F];
2461 ch
[i
+1] = HEX_CHARS
[d
& 0x0F];
2463 return new String(ch
);
2467 * Convert a byte array into a hex string
2469 public static String
toHex(byte[] b
) {
2470 return toHex(b
, 0, b
.length
);
2473 private static int hexCharToNibble(char ch
) {
2474 if (ch
<= '9' && ch
>= '0') {
2476 } else if (ch
>= 'a' && ch
<= 'f') {
2477 return ch
- 'a' + 10;
2478 } else if (ch
>= 'A' && ch
<= 'F') {
2479 return ch
- 'A' + 10;
2481 throw new IllegalArgumentException("Invalid hex char: " + ch
);
2484 private static byte hexCharsToByte(char c1
, char c2
) {
2485 return (byte) ((hexCharToNibble(c1
) << 4) | hexCharToNibble(c2
));
2489 * Create a byte array from a string of hash digits. The length of the
2490 * string must be a multiple of 2
2493 public static byte[] fromHex(String hex
) {
2494 checkArgument(hex
.length() % 2 == 0, "length must be a multiple of 2");
2495 int len
= hex
.length();
2496 byte[] b
= new byte[len
/ 2];
2497 for (int i
= 0; i
< len
; i
+= 2) {
2498 b
[i
/ 2] = hexCharsToByte(hex
.charAt(i
),hex
.charAt(i
+1));
2506 * @return Index of delimiter having started from start of <code>b</code> moving rightward.
2508 public static int searchDelimiterIndex(final byte[] b
, int offset
, final int length
,
2509 final int delimiter
) {
2511 throw new IllegalArgumentException("Passed buffer is null");
2514 for (int i
= offset
; i
< length
+ offset
; i
++) {
2515 if (b
[i
] == delimiter
) {
2524 * Find index of passed delimiter walking from end of buffer backwards.
2528 * @return Index of delimiter
2530 public static int searchDelimiterIndexInReverse(final byte[] b
, final int offset
,
2531 final int length
, final int delimiter
) {
2533 throw new IllegalArgumentException("Passed buffer is null");
2536 for (int i
= (offset
+ length
) - 1; i
>= offset
; i
--) {
2537 if (b
[i
] == delimiter
) {
2545 public static int findCommonPrefix(byte[] left
, byte[] right
, int leftLength
, int rightLength
,
2546 int leftOffset
, int rightOffset
) {
2547 int length
= Math
.min(leftLength
, rightLength
);
2550 while (result
< length
&& left
[leftOffset
+ result
] == right
[rightOffset
+ result
]) {