HBASE-26921 Rewrite the counting cells part in TestMultiVersions (#4316)
[hbase.git] / hbase-common / src / main / java / org / apache / hadoop / hbase / util / Bytes.java
blobaf6854109b5743f5d4e47dac752f1b3498837d2c
1 /**
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;
54 /**
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);
74 /**
75 * Size of boolean in bytes
77 public static final int SIZEOF_BOOLEAN = Byte.SIZE / Byte.SIZE;
79 /**
80 * Size of byte in bytes
82 public static final int SIZEOF_BYTE = SIZEOF_BOOLEAN;
84 /**
85 * Size of char in bytes
87 public static final int SIZEOF_CHAR = Character.SIZE / Byte.SIZE;
89 /**
90 * Size of double in bytes
92 public static final int SIZEOF_DOUBLE = Double.SIZE / Byte.SIZE;
94 /**
95 * Size of float in bytes
97 public static final int SIZEOF_FLOAT = Float.SIZE / Byte.SIZE;
99 /**
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;
141 private int offset;
142 private int length;
145 * Create a zero-size sequence.
147 public Bytes() {
148 super();
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
161 * <code>ibw</code>.
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,
175 final int length) {
176 this.bytes = bytes;
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");
190 return this.bytes;
194 * @param b Use passed bytes as backing array for this instance.
196 public void set(final byte [] b) {
197 set(b, 0, b.length);
201 * @param b Use passed bytes as backing array for this instance.
202 * @param offset
203 * @param length
205 public void set(final byte [] b, final int offset, final int length) {
206 this.bytes = b;
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");
219 return this.length;
223 * @return offset
225 public int getOffset(){
226 return this.offset;
229 @Override
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.
240 @Override
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
249 * @param that
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)
262 @Override
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;
270 return false;
274 * @see Object#toString()
276 @Override
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);
291 return results;
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 []> {
306 * Constructor
308 public ByteArrayComparator() {
309 super();
311 @Override
312 public int compare(byte [] left, byte [] right) {
313 return compareTo(left, right);
315 @Override
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 {
332 @Override
333 public int compare(byte[] left, byte[] right) {
334 return compare(left, 0, left.length, right, 0, right.length);
336 @Override
337 public int compare(byte[] b1, int s1, int l1, byte[] b2, int s2, int l2) {
338 if (b1 == b2 && s1 == s2 && l1 == l2) {
339 return 0;
341 if (l1 == 0) {
342 return l2; //0 or positive
344 if (l2 == 0) {
345 return -1;
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)
368 throws IOException {
369 int len = WritableUtils.readVInt(in);
370 if (len < 0) {
371 throw new NegativeArraySizeException(Integer.toString(len));
373 byte [] result = new byte[len];
374 in.readFully(result, 0, len);
375 return result;
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) {
385 try {
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)
399 throws IOException {
400 if(b == null) {
401 WritableUtils.writeVInt(out, 0);
402 } else {
403 writeByteArray(out, b, 0, b.length);
408 * Write byte-array to out with a vint length prefix.
409 * @param out output stream
410 * @param b array
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)
417 throws IOException {
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) {
463 bytes[offset] = b;
464 return offset + 1;
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);
477 return 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();
492 dup.position(0);
493 return readBytes(dup);
496 private static byte[] readBytes(ByteBuffer buf) {
497 byte [] result = new byte[buf.remaining()];
498 buf.get(result);
499 return result;
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) {
507 if (b == null) {
508 return null;
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,
520 String sep,
521 final byte [] b2) {
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) {
534 if (b == null) {
535 return null;
537 int len = b.length - off;
538 if (len <= 0) {
539 return "";
541 try {
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) {
559 if (b == null) {
560 return null;
562 if (len == 0) {
563 return "";
565 try {
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
577 * @return string
578 * @see #toStringBinary(byte[], int, int)
580 public static String toStringBinary(final byte [] b) {
581 if (b == null)
582 return "null";
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) {
598 if (buf == null)
599 return "null";
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:
613 * \x00 \x05 etc
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);
629 } else {
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) {
639 return
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'));
653 // else
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()];
660 int size = 0;
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) ||
670 !isHexDigit(hd2)) {
671 // bogus escape code, ignore:
672 continue;
674 // turn hex ASCII digit -> number
675 byte d = (byte) ((toBinaryFromHex((byte)hd1) << 4) + toBinaryFromHex((byte)hd2));
677 b[size++] = d;
678 i += 3; // skip 3
679 } else {
680 b[size++] = (byte) ch;
683 // resize:
684 byte [] b2 = new byte[size];
685 System.arraycopy(b, 0, b2, 0, size);
686 return b2;
690 * Converts a string to a UTF-8 byte array.
691 * @param s string
692 * @return the byte array
694 public static byte[] toBytes(String s) {
695 try {
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.
707 * @param b value
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)}
716 * @param b array
717 * @return True or false.
719 public static boolean toBoolean(final byte [] b) {
720 if (b.length != 1) {
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--) {
735 b[i] = (byte) val;
736 val >>>= 8;
738 b[0] = (byte) val;
739 return b;
743 * Converts a byte array to a long value. Reverses
744 * {@link #toBytes(long)}
745 * @param bytes array
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.
756 * @param bytes bytes
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,
783 final int offset,
784 final int length,
785 final int expectedLength) {
786 String reason;
787 if (length != expectedLength) {
788 reason = "Wrong length: " + length + ", expected " + expectedLength;
789 } else {
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) {
847 // Encode it as int
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
871 * @param d value
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.
882 * @param d value
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
892 * does.
894 * @param val value
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--) {
900 b[i] = (byte) val;
901 val >>>= 8;
903 b[0] = (byte) val;
904 return b;
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
949 * indicated.
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);
956 int n = 0;
957 for(int i = offset; i < (offset + length); i++) {
958 n <<= 8;
959 n ^= bytes[i] & 0xFF;
961 return n;
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.
983 * @param val value
984 * @return the byte array
986 public static byte[] toBytes(short val) {
987 byte[] b = new byte[SIZEOF_SHORT];
988 b[1] = (byte) val;
989 val >>= 8;
990 b[0] = (byte) val;
991 return b;
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;
1077 val >>= 8;
1078 bytes[offset] = (byte) val;
1079 return offset + SIZEOF_SHORT;
1083 * Convert a BigDecimal value to a byte array
1085 * @param val
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);
1093 return result;
1098 * Converts a byte array to a BigDecimal
1100 * @param bytes
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
1110 * @param bytes
1111 * @param offset
1112 * @param length
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)) {
1118 return null;
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) {
1137 return offset;
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) {
1151 long i = vint;
1152 int size = WritableUtils.getVIntSize(i);
1153 byte [] result = new byte[size];
1154 int offset = 0;
1155 if (i >= -112 && i <= 127) {
1156 result[offset] = (byte) i;
1157 return result;
1160 int len = -112;
1161 if (i < 0) {
1162 i ^= -1L; // take one's complement'
1163 len = -120;
1166 long tmp = i;
1167 while (tmp != 0) {
1168 tmp = tmp >> 8;
1169 len--;
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);
1181 return result;
1185 * @param buffer buffer to convert
1186 * @return vint bytes as an integer.
1188 public static long bytesToVint(final byte [] buffer) {
1189 int offset = 0;
1190 byte firstByte = buffer[offset++];
1191 int len = WritableUtils.decodeVIntSize(firstByte);
1192 if (len == 1) {
1193 return firstByte;
1195 long i = 0;
1196 for (int idx = 0; idx < len-1; idx++) {
1197 byte b = buffer[offset++];
1198 i = i << 8;
1199 i = i | (b & 0xFF);
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);
1213 if (len == 1) {
1214 return firstByte;
1216 long i = 0;
1217 for (int idx = 0; idx < len-1; idx++) {
1218 byte b = buffer[offset + 1 + idx];
1219 i = i << 8;
1220 i = i | (b & 0xFF);
1222 return (WritableUtils.isNegativeVInt(firstByte) ? ~i : i);
1226 * @param left left operand
1227 * @param right right operand
1228 * @return 0 if equal, &lt; 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, &lt; 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> {
1253 int compareTo(
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() {
1284 try {
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();
1290 return converter;
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() {}
1301 @Override
1302 long toLong(byte[] bytes, int offset, int length) {
1303 long l = 0;
1304 for(int i = offset; i < offset + length; i++) {
1305 l <<= 8;
1306 l ^= bytes[i] & 0xFF;
1308 return l;
1311 @Override
1312 int putLong(byte[] bytes, int offset, long val) {
1313 for(int i = offset + 7; i > offset; i--) {
1314 bytes[i] = (byte) val;
1315 val >>>= 8;
1317 bytes[offset] = (byte) val;
1318 return offset + SIZEOF_LONG;
1321 @Override
1322 int toInt(byte[] bytes, int offset, int length) {
1323 int n = 0;
1324 for(int i = offset; i < (offset + length); i++) {
1325 n <<= 8;
1326 n ^= bytes[i] & 0xFF;
1328 return n;
1331 @Override
1332 int putInt(byte[] bytes, int offset, int val) {
1333 for(int i= offset + 3; i > offset; i--) {
1334 bytes[i] = (byte) val;
1335 val >>>= 8;
1337 bytes[offset] = (byte) val;
1338 return offset + SIZEOF_INT;
1341 @Override
1342 short toShort(byte[] bytes, int offset, int length) {
1343 short n = 0;
1344 n = (short) ((n ^ bytes[offset]) & 0xFF);
1345 n = (short) (n << 8);
1346 n ^= (short) (bytes[offset+1] & 0xFF);
1347 return n;
1350 @Override
1351 int putShort(byte[] bytes, int offset, short val) {
1352 bytes[offset+1] = (byte) val;
1353 val >>= 8;
1354 bytes[offset] = (byte) val;
1355 return offset + SIZEOF_SHORT;
1359 protected static final class UnsafeConverter extends Converter {
1361 public UnsafeConverter() {}
1363 static {
1364 if (!UNSAFE_UNALIGNED) {
1365 // It doesn't matter what we throw;
1366 // it's swallowed in getBestComparer().
1367 throw new Error();
1370 // sanity check - this should never fail
1371 if (HBasePlatformDependent.arrayIndexScale(byte[].class) != 1) {
1372 throw new AssertionError();
1376 @Override
1377 long toLong(byte[] bytes, int offset, int length) {
1378 return UnsafeAccess.toLong(bytes, offset);
1381 @Override
1382 int putLong(byte[] bytes, int offset, long val) {
1383 return UnsafeAccess.putLong(bytes, offset, val);
1386 @Override
1387 int toInt(byte[] bytes, int offset, int length) {
1388 return UnsafeAccess.toInt(bytes, offset);
1391 @Override
1392 int putInt(byte[] bytes, int offset, int val) {
1393 return UnsafeAccess.putInt(bytes, offset, val);
1396 @Override
1397 short toShort(byte[] bytes, int offset, int length) {
1398 return UnsafeAccess.toShort(bytes, offset);
1401 @Override
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() {
1425 try {
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];
1432 return comparer;
1433 } catch (Throwable t) { // ensure we really catch *everything*
1434 return lexicographicalComparerJavaImpl();
1438 enum PureJavaComparer implements Comparer<byte[]> {
1439 INSTANCE;
1441 @Override
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) {
1448 return 0;
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);
1456 if (a != b) {
1457 return a - b;
1460 return length1 - length2;
1464 enum UnsafeComparer implements Comparer<byte[]> {
1465 INSTANCE;
1467 static {
1468 if (!UNSAFE_UNALIGNED) {
1469 // It doesn't matter what we throw;
1470 // it's swallowed in getBestComparer().
1471 throw new Error();
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.
1491 @Override
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) {
1499 return 0;
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;
1506 int i;
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);
1515 if (lw != rw) {
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);
1537 if (a != b) {
1538 return a - b;
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) {
1573 return true;
1575 // different lengths fast check
1576 if (leftLen != rightLen) {
1577 return false;
1579 if (leftLen == 0) {
1580 return true;
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()) {
1607 return false;
1610 return true;
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);
1636 * @param b value
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
1649 * Maps.
1651 public static Integer mapKey(final byte [] b) {
1652 return hashCode(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
1659 * Maps.
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);
1685 return result;
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) {
1693 int length = 0;
1694 for (int i = 0; i < arrays.length; i++) {
1695 length += arrays[i].length;
1697 byte [] result = new byte[length];
1698 int index = 0;
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;
1703 return result;
1707 * @param a array
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) {
1713 return null;
1715 byte [] result = new byte[length];
1716 System.arraycopy(a, 0, result, 0, length);
1717 return result;
1721 * @param a array
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) {
1727 return null;
1729 byte [] result = new byte[length];
1730 System.arraycopy(a, a.length - length, result, 0, length);
1731 return result;
1735 * @param a array
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++) {
1742 padding[i] = 0;
1744 return add(padding,a);
1748 * @param a array
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++) {
1755 padding[i] = 0;
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][];
1788 int i = 0;
1789 Iterable<byte[]> iter = iterateOnSplits(a, b, inclusive, num);
1790 if (iter == null)
1791 return null;
1792 for (byte[] elem : iter) {
1793 ret[i++] = elem;
1795 return ret;
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)
1813 byte [] aPadded;
1814 byte [] bPadded;
1815 if (a.length < b.length) {
1816 aPadded = padTail(a, b.length - a.length);
1817 bPadded = b;
1818 } else if (b.length < a.length) {
1819 aPadded = a;
1820 bPadded = padTail(b, a.length - b.length);
1821 } else {
1822 aPadded = a;
1823 bPadded = b;
1825 if (compareTo(aPadded,bPadded) >= 0) {
1826 throw new IllegalArgumentException("b <= a");
1828 if (num <= 0) {
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);
1835 if (inclusive) {
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;
1854 try {
1855 intervalBI = diffBI.divide(splitsBI);
1856 } catch(Exception e) {
1857 LOG.error("Exception caught during division", e);
1858 return null;
1861 final Iterator<byte[]> iterator = new Iterator<byte[]>() {
1862 private int i = -1;
1864 @Override
1865 public boolean hasNext() {
1866 return i < num+1;
1869 @Override
1870 public byte[] next() {
1871 i++;
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();
1877 if (padded[1] == 0)
1878 padded = tail(padded, padded.length - 2);
1879 else
1880 padded = tail(padded, padded.length - 1);
1881 return padded;
1884 @Override
1885 public void remove() {
1886 throw new UnsupportedOperationException();
1891 return new Iterable<byte[]>() {
1892 @Override
1893 public Iterator<byte[]> iterator() {
1894 return iterator;
1900 * @param bytes array to hash
1901 * @param offset offset to start from
1902 * @param length length to hash
1903 * */
1904 public static int hashCode(byte[] bytes, int offset, int length) {
1905 int hash = 1;
1906 for (int i = offset; i < offset + length; i++)
1907 hash = (31 * hash) + bytes[i];
1908 return hash;
1912 * @param t operands
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]);
1920 return result;
1924 * @param t operands
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]);
1932 return result;
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][];
1951 result[0] = column;
1952 return result;
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) {
1970 int low = 0;
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
1980 if (cmp > 0)
1981 low = mid + 1;
1982 // key lives below the midpoint
1983 else if (cmp < 0)
1984 high = mid - 1;
1985 // BAM. how often does this really happen?
1986 else
1987 return mid;
1989 return -(low + 1);
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) {
2007 int low = 0;
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
2015 if (cmp > 0)
2016 low = mid + 1;
2017 // key lives below the midpoint
2018 else if (cmp < 0)
2019 high = mid - 1;
2020 // BAM. how often does this really happen?
2021 else
2022 return mid;
2024 return - (low+1);
2028 * Bytewise binary increment/deincrement of long contained in byte array
2029 * on given amount.
2031 * @param value - array of bytes containing long (length &lt;= 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)
2037 byte[] val = value;
2038 if (val.length < SIZEOF_LONG) {
2039 // Hopefully this doesn't happen too often.
2040 byte [] newvalue;
2041 if (val[0] < 0) {
2042 newvalue = new byte[]{-1, -1, -1, -1, -1, -1, -1, -1};
2043 } else {
2044 newvalue = new byte[SIZEOF_LONG];
2046 System.arraycopy(val, 0, newvalue, newvalue.length - val.length,
2047 val.length);
2048 val = newvalue;
2049 } else if (val.length > SIZEOF_LONG) {
2050 throw new IllegalArgumentException("Increment Bytes - value too big: " +
2051 val.length);
2053 if(amount == 0) return val;
2054 if(val[0] < 0){
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) {
2062 long amo = amount;
2063 int sign = 1;
2064 if (amount < 0) {
2065 amo = -amount;
2066 sign = -1;
2068 for(int i=0;i<value.length;i++) {
2069 int cur = ((int)amo % 256) * sign;
2070 amo = (amo >> 8);
2071 int val = value[value.length-i-1] & 0x0ff;
2072 int total = val + cur;
2073 if(total > 255) {
2074 amo += sign;
2075 total %= 256;
2076 } else if (total < 0) {
2077 amo -= sign;
2079 value[value.length-i-1] = (byte)total;
2080 if (amo == 0) return value;
2082 return value;
2085 /* increment/deincrement for negative value */
2086 private static byte [] binaryIncrementNeg(byte [] value, long amount) {
2087 long amo = amount;
2088 int sign = 1;
2089 if (amount < 0) {
2090 amo = -amount;
2091 sign = -1;
2093 for(int i=0;i<value.length;i++) {
2094 int cur = ((int)amo % 256) * sign;
2095 amo = (amo >> 8);
2096 int val = ((~value[value.length-i-1]) & 0x0ff) + 1;
2097 int total = cur - val;
2098 if(total >= 0) {
2099 amo += sign;
2100 } else if (total < -256) {
2101 amo -= sign;
2102 total %= 256;
2104 value[value.length-i-1] = (byte)total;
2105 if (amo == 0) return value;
2107 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);
2121 out.writeBytes(s);
2122 for (int i = 0; i < size - s.length(); ++i)
2123 out.writeByte(0);
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];
2132 in.readFully(b);
2133 int n = b.length;
2134 while (n > 0 && b[n - 1] == 0)
2135 --n;
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);
2150 return result;
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
2158 * @param offset
2159 * @param length
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);
2165 return result;
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) {
2188 low = mid + 1;
2189 } else if (midVal > unsignedKey) {
2190 high = mid - 1;
2191 } else {
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);
2207 if (copy == null) {
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
2212 copy[i] = 0;
2213 } else {
2214 ++copy[i];
2215 return copy;
2218 // we maxed out the array
2219 byte[] out = new byte[copy.length + 1];
2220 out[0] = 1;
2221 System.arraycopy(copy, 0, out, 1, copy.length);
2222 return out;
2225 public static boolean equals(List<byte[]> a, List<byte[]> b) {
2226 if (a == null) {
2227 if (b == null) {
2228 return true;
2230 return false;
2232 if (b == null) {
2233 return false;
2235 if (a.size() != b.size()) {
2236 return false;
2238 for (int i = 0; i < a.size(); ++i) {
2239 if (!Bytes.equals(a.get(i), b.get(i))) {
2240 return false;
2243 return true;
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) {
2251 return false;
2253 previous = array;
2256 return true;
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)));
2265 return byteArrays;
2269 * Returns the index of the first appearance of the value {@code target} in
2270 * {@code array}.
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) {
2280 return i;
2283 return -1;
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) {
2301 return 0;
2304 outer:
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]) {
2308 continue outer;
2311 return i;
2313 return -1;
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.
2344 * @param b
2345 * @param offset
2346 * @param length
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
2361 * <p>
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) {
2367 RNG.nextBytes(b);
2371 * Fill given array with random bytes at the specified position.
2372 * <p>
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];
2384 RNG.nextBytes(buf);
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
2401 * generator.
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
2430 * @param srcBytes
2431 * @param multiNum
2432 * @return byte array
2434 public static byte[] multiple(byte[] srcBytes, int multiNum) {
2435 if (multiNum <= 0) {
2436 return new byte[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,
2441 srcBytes.length);
2443 return result;
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') {
2475 return 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
2491 * @param hex
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));
2500 return b;
2504 * @param b
2505 * @param delimiter
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) {
2510 if (b == null) {
2511 throw new IllegalArgumentException("Passed buffer is null");
2513 int result = -1;
2514 for (int i = offset; i < length + offset; i++) {
2515 if (b[i] == delimiter) {
2516 result = i;
2517 break;
2520 return result;
2524 * Find index of passed delimiter walking from end of buffer backwards.
2526 * @param b
2527 * @param delimiter
2528 * @return Index of delimiter
2530 public static int searchDelimiterIndexInReverse(final byte[] b, final int offset,
2531 final int length, final int delimiter) {
2532 if (b == null) {
2533 throw new IllegalArgumentException("Passed buffer is null");
2535 int result = -1;
2536 for (int i = (offset + length) - 1; i >= offset; i--) {
2537 if (b[i] == delimiter) {
2538 result = i;
2539 break;
2542 return result;
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);
2548 int result = 0;
2550 while (result < length && left[leftOffset + result] == right[rightOffset + result]) {
2551 result++;
2553 return result;