View Javadoc

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
9    *
10   *     http://www.apache.org/licenses/LICENSE-2.0
11   *
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.
17   */
18  package org.apache.hadoop.hbase.util;
19  
20  import static com.google.common.base.Preconditions.checkArgument;
21  import static com.google.common.base.Preconditions.checkNotNull;
22  import static com.google.common.base.Preconditions.checkPositionIndex;
23  
24  import com.google.common.collect.Lists;
25  import java.io.DataInput;
26  import java.io.DataOutput;
27  import java.io.IOException;
28  import java.math.BigDecimal;
29  import java.math.BigInteger;
30  import java.nio.ByteBuffer;
31  import java.nio.ByteOrder;
32  import java.nio.charset.Charset;
33  import java.security.SecureRandom;
34  import java.util.Arrays;
35  import java.util.Collection;
36  import java.util.Comparator;
37  import java.util.Iterator;
38  import java.util.List;
39  import org.apache.commons.logging.Log;
40  import org.apache.commons.logging.LogFactory;
41  import org.apache.hadoop.hbase.classification.InterfaceAudience;
42  import org.apache.hadoop.hbase.classification.InterfaceStability;
43  import org.apache.hadoop.hbase.Cell;
44  import org.apache.hadoop.hbase.KeyValue;
45  import org.apache.hadoop.hbase.util.Bytes.LexicographicalComparerHolder.UnsafeComparer;
46  import org.apache.hadoop.io.RawComparator;
47  import org.apache.hadoop.io.WritableComparator;
48  import org.apache.hadoop.io.WritableUtils;
49  import sun.misc.Unsafe;
50  
51  /**
52   * Utility class that handles byte arrays, conversions to/from other types,
53   * comparisons, hash code generation, manufacturing keys for HashMaps or
54   * HashSets, etc.
55   */
56  @SuppressWarnings("restriction")
57  @InterfaceAudience.Public
58  @InterfaceStability.Stable
59  public class Bytes implements Comparable<Bytes> {
60    //HConstants.UTF8_ENCODING should be updated if this changed
61    /** When we encode strings, we always specify UTF8 encoding */
62    private static final String UTF8_ENCODING = "UTF-8";
63  
64    //HConstants.UTF8_CHARSET should be updated if this changed
65    /** When we encode strings, we always specify UTF8 encoding */
66    private static final Charset UTF8_CHARSET = Charset.forName(UTF8_ENCODING);
67  
68    //HConstants.EMPTY_BYTE_ARRAY should be updated if this changed
69    private static final byte [] EMPTY_BYTE_ARRAY = new byte [0];
70  
71    private static final Log LOG = LogFactory.getLog(Bytes.class);
72  
73    /**
74     * Size of boolean in bytes
75     */
76    public static final int SIZEOF_BOOLEAN = Byte.SIZE / Byte.SIZE;
77  
78    /**
79     * Size of byte in bytes
80     */
81    public static final int SIZEOF_BYTE = SIZEOF_BOOLEAN;
82  
83    /**
84     * Size of char in bytes
85     */
86    public static final int SIZEOF_CHAR = Character.SIZE / Byte.SIZE;
87  
88    /**
89     * Size of double in bytes
90     */
91    public static final int SIZEOF_DOUBLE = Double.SIZE / Byte.SIZE;
92  
93    /**
94     * Size of float in bytes
95     */
96    public static final int SIZEOF_FLOAT = Float.SIZE / Byte.SIZE;
97  
98    /**
99     * Size of int in bytes
100    */
101   public static final int SIZEOF_INT = Integer.SIZE / Byte.SIZE;
102 
103   /**
104    * Size of long in bytes
105    */
106   public static final int SIZEOF_LONG = Long.SIZE / Byte.SIZE;
107 
108   /**
109    * Size of short in bytes
110    */
111   public static final int SIZEOF_SHORT = Short.SIZE / Byte.SIZE;
112 
113   /**
114    * Mask to apply to a long to reveal the lower int only. Use like this:
115    * int i = (int)(0xFFFFFFFF00000000l ^ some_long_value);
116    */
117   public static final long MASK_FOR_LOWER_INT_IN_LONG = 0xFFFFFFFF00000000l;
118 
119   /**
120    * Estimate of size cost to pay beyond payload in jvm for instance of byte [].
121    * Estimate based on study of jhat and jprofiler numbers.
122    */
123   // JHat says BU is 56 bytes.
124   // SizeOf which uses java.lang.instrument says 24 bytes. (3 longs?)
125   public static final int ESTIMATED_HEAP_TAX = 16;
126 
127   @InterfaceAudience.Private
128   static final boolean UNSAFE_UNALIGNED = UnsafeAvailChecker.unaligned();
129 
130   /**
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
135    */
136   final public static int len(byte[] b) {
137     return b == null ? 0 : b.length;
138   }
139 
140   private byte[] bytes;
141   private int offset;
142   private int length;
143 
144   /**
145    * Create a zero-size sequence.
146    */
147   public Bytes() {
148     super();
149   }
150 
151   /**
152    * Create a Bytes using the byte array as the initial value.
153    * @param bytes This array becomes the backing storage for the object.
154    */
155   public Bytes(byte[] bytes) {
156     this(bytes, 0, bytes.length);
157   }
158 
159   /**
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.
163    */
164   public Bytes(final Bytes ibw) {
165     this(ibw.get(), ibw.getOffset(), ibw.getLength());
166   }
167 
168   /**
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
173    */
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;
179   }
180 
181   /**
182    * Get the data from the Bytes.
183    * @return The data is only valid between offset and offset+length.
184    */
185   public byte[] get() {
186     if (this.bytes == null) {
187       throw new IllegalStateException("Uninitialiized. Null constructor " +
188           "called w/o accompaying readFields invocation");
189     }
190     return this.bytes;
191   }
192 
193   /**
194    * @param b Use passed bytes as backing array for this instance.
195    */
196   public void set(final byte[] b) {
197     set(b, 0, b.length);
198   }
199 
200   /**
201    * @param b Use passed bytes as backing array for this instance.
202    * @param offset
203    * @param length
204    */
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;
209   }
210 
211   /**
212    * @return the number of valid bytes in the buffer
213    */
214   public int getLength() {
215     if (this.bytes == null) {
216       throw new IllegalStateException("Uninitialiized. Null constructor " +
217           "called w/o accompaying readFields invocation");
218     }
219     return this.length;
220   }
221 
222   /**
223    * @return offset
224    */
225   public int getOffset(){
226     return this.offset;
227   }
228   @Override
229   public int hashCode() {
230     return Bytes.hashCode(bytes, offset, length);
231   }
232 
233   /**
234    * Define the sort order of the Bytes.
235    * @param that The other bytes writable
236    * @return Positive if left is bigger than right, 0 if they are equal, and
237    *         negative if left is smaller than right.
238    */
239   @Override
240   public int compareTo(Bytes that) {
241     return BYTES_RAWCOMPARATOR.compare(
242         this.bytes, this.offset, this.length,
243         that.bytes, that.offset, that.length);
244   }
245 
246   /**
247    * Compares the bytes in this object to the specified byte array
248    * @param that
249    * @return Positive if left is bigger than right, 0 if they are equal, and
250    *         negative if left is smaller than right.
251    */
252   public int compareTo(final byte[] that) {
253     return BYTES_RAWCOMPARATOR.compare(
254         this.bytes, this.offset, this.length,
255         that, 0, that.length);
256   }
257 
258   /**
259    * @see Object#equals(Object)
260    */
261   @Override
262   public boolean equals(Object that) {
263     if (that == this) {
264       return true;
265     }
266     if (that instanceof Bytes) {
267       return compareTo((Bytes)that) == 0;
268     }
269     return false;
270   }
271 
272   /**
273    * @see Object#toString()
274    */
275   @Override
276   public String toString() {
277     return Bytes.toString(bytes, offset, length);
278   }
279 
280   /**
281    * Returns a copy of the bytes referred to by this writable
282    */
283   public byte[] copyBytes() {
284     return Arrays.copyOfRange(bytes, offset, offset+length);
285   }
286 
287   /**
288    * Byte array comparator class.
289    */
290   @InterfaceAudience.Public
291   @InterfaceStability.Stable
292   public static class ByteArrayComparator implements RawComparator<byte []> {
293     /**
294      * Constructor
295      */
296     public ByteArrayComparator() {
297       super();
298     }
299     @Override
300     public int compare(byte [] left, byte [] right) {
301       return compareTo(left, right);
302     }
303     @Override
304     public int compare(byte [] b1, int s1, int l1, byte [] b2, int s2, int l2) {
305       return LexicographicalComparerHolder.BEST_COMPARER.
306         compareTo(b1, s1, l1, b2, s2, l2);
307     }
308   }
309 
310   /**
311    * A {@link ByteArrayComparator} that treats the empty array as the largest value.
312    * This is useful for comparing row end keys for regions.
313    */
314   // TODO: unfortunately, HBase uses byte[0] as both start and end keys for region
315   // boundaries. Thus semantically, we should treat empty byte array as the smallest value
316   // while comparing row keys, start keys etc; but as the largest value for comparing
317   // region boundaries for endKeys.
318   @InterfaceAudience.Public
319   @InterfaceStability.Stable
320   public static class RowEndKeyComparator extends ByteArrayComparator {
321     @Override
322     public int compare(byte[] left, byte[] right) {
323       return compare(left, 0, left.length, right, 0, right.length);
324     }
325     @Override
326     public int compare(byte[] b1, int s1, int l1, byte[] b2, int s2, int l2) {
327       if (b1 == b2 && s1 == s2 && l1 == l2) {
328         return 0;
329       }
330       if (l1 == 0) {
331         return l2; //0 or positive
332       }
333       if (l2 == 0) {
334         return -1;
335       }
336       return super.compare(b1, s1, l1, b2, s2, l2);
337     }
338   }
339 
340   /**
341    * Pass this to TreeMaps where byte [] are keys.
342    */
343   public final static Comparator<byte []> BYTES_COMPARATOR = new ByteArrayComparator();
344 
345   /**
346    * Use comparing byte arrays, byte-by-byte
347    */
348   public final static RawComparator<byte []> BYTES_RAWCOMPARATOR = new ByteArrayComparator();
349 
350   /**
351    * Read byte-array written with a WritableableUtils.vint prefix.
352    * @param in Input to read from.
353    * @return byte array read off <code>in</code>
354    * @throws IOException e
355    */
356   public static byte [] readByteArray(final DataInput in)
357   throws IOException {
358     int len = WritableUtils.readVInt(in);
359     if (len < 0) {
360       throw new NegativeArraySizeException(Integer.toString(len));
361     }
362     byte [] result = new byte[len];
363     in.readFully(result, 0, len);
364     return result;
365   }
366 
367   /**
368    * Read byte-array written with a WritableableUtils.vint prefix.
369    * IOException is converted to a RuntimeException.
370    * @param in Input to read from.
371    * @return byte array read off <code>in</code>
372    */
373   public static byte [] readByteArrayThrowsRuntime(final DataInput in) {
374     try {
375       return readByteArray(in);
376     } catch (Exception e) {
377       throw new RuntimeException(e);
378     }
379   }
380 
381   /**
382    * Write byte-array with a WritableableUtils.vint prefix.
383    * @param out output stream to be written to
384    * @param b array to write
385    * @throws IOException e
386    */
387   public static void writeByteArray(final DataOutput out, final byte [] b)
388   throws IOException {
389     if(b == null) {
390       WritableUtils.writeVInt(out, 0);
391     } else {
392       writeByteArray(out, b, 0, b.length);
393     }
394   }
395 
396   /**
397    * Write byte-array to out with a vint length prefix.
398    * @param out output stream
399    * @param b array
400    * @param offset offset into array
401    * @param length length past offset
402    * @throws IOException e
403    */
404   public static void writeByteArray(final DataOutput out, final byte [] b,
405       final int offset, final int length)
406   throws IOException {
407     WritableUtils.writeVInt(out, length);
408     out.write(b, offset, length);
409   }
410 
411   /**
412    * Write byte-array from src to tgt with a vint length prefix.
413    * @param tgt target array
414    * @param tgtOffset offset into target array
415    * @param src source array
416    * @param srcOffset source offset
417    * @param srcLength source length
418    * @return New offset in src array.
419    */
420   public static int writeByteArray(final byte [] tgt, final int tgtOffset,
421       final byte [] src, final int srcOffset, final int srcLength) {
422     byte [] vint = vintToBytes(srcLength);
423     System.arraycopy(vint, 0, tgt, tgtOffset, vint.length);
424     int offset = tgtOffset + vint.length;
425     System.arraycopy(src, srcOffset, tgt, offset, srcLength);
426     return offset + srcLength;
427   }
428 
429   /**
430    * Put bytes at the specified byte array position.
431    * @param tgtBytes the byte array
432    * @param tgtOffset position in the array
433    * @param srcBytes array to write out
434    * @param srcOffset source offset
435    * @param srcLength source length
436    * @return incremented offset
437    */
438   public static int putBytes(byte[] tgtBytes, int tgtOffset, byte[] srcBytes,
439       int srcOffset, int srcLength) {
440     System.arraycopy(srcBytes, srcOffset, tgtBytes, tgtOffset, srcLength);
441     return tgtOffset + srcLength;
442   }
443 
444   /**
445    * Write a single byte out to the specified byte array position.
446    * @param bytes the byte array
447    * @param offset position in the array
448    * @param b byte to write out
449    * @return incremented offset
450    */
451   public static int putByte(byte[] bytes, int offset, byte b) {
452     bytes[offset] = b;
453     return offset + 1;
454   }
455 
456   /**
457    * Add the whole content of the ByteBuffer to the bytes arrays. The ByteBuffer is modified.
458    * @param bytes the byte array
459    * @param offset position in the array
460    * @param buf ByteBuffer to write out
461    * @return incremented offset
462    */
463   public static int putByteBuffer(byte[] bytes, int offset, ByteBuffer buf) {
464     int len = buf.remaining();
465     buf.get(bytes, offset, len);
466     return offset + len;
467   }
468 
469   /**
470    * Returns a new byte array, copied from the given {@code buf},
471    * from the index 0 (inclusive) to the limit (exclusive),
472    * regardless of the current position.
473    * The position and the other index parameters are not changed.
474    *
475    * @param buf a byte buffer
476    * @return the byte array
477    * @see #getBytes(ByteBuffer)
478    */
479   public static byte[] toBytes(ByteBuffer buf) {
480     ByteBuffer dup = buf.duplicate();
481     dup.position(0);
482     return readBytes(dup);
483   }
484 
485   private static byte[] readBytes(ByteBuffer buf) {
486     byte [] result = new byte[buf.remaining()];
487     buf.get(result);
488     return result;
489   }
490 
491   /**
492    * @param b Presumed UTF-8 encoded byte array.
493    * @return String made from <code>b</code>
494    */
495   public static String toString(final byte [] b) {
496     if (b == null) {
497       return null;
498     }
499     return toString(b, 0, b.length);
500   }
501 
502   /**
503    * Joins two byte arrays together using a separator.
504    * @param b1 The first byte array.
505    * @param sep The separator to use.
506    * @param b2 The second byte array.
507    */
508   public static String toString(final byte [] b1,
509                                 String sep,
510                                 final byte [] b2) {
511     return toString(b1, 0, b1.length) + sep + toString(b2, 0, b2.length);
512   }
513 
514   /**
515    * This method will convert utf8 encoded bytes into a string. If the given byte array is null,
516    * this method will return null.
517    * @param b Presumed UTF-8 encoded byte array.
518    * @param off offset into array
519    * @return String made from <code>b</code> or null
520    */
521   public static String toString(final byte[] b, int off) {
522     if (b == null) {
523       return null;
524     }
525     int len = b.length - off;
526     if (len <= 0) {
527       return "";
528     }
529     return new String(b, off, len, UTF8_CHARSET);
530   }
531 
532   /**
533    * This method will convert utf8 encoded bytes into a string. If
534    * the given byte array is null, this method will return null.
535    *
536    * @param b Presumed UTF-8 encoded byte array.
537    * @param off offset into array
538    * @param len length of utf-8 sequence
539    * @return String made from <code>b</code> or null
540    */
541   public static String toString(final byte [] b, int off, int len) {
542     if (b == null) {
543       return null;
544     }
545     if (len == 0) {
546       return "";
547     }
548     return new String(b, off, len, UTF8_CHARSET);
549   }
550 
551   /**
552    * Write a printable representation of a byte array.
553    *
554    * @param b byte array
555    * @return string
556    * @see #toStringBinary(byte[], int, int)
557    */
558   public static String toStringBinary(final byte [] b) {
559     if (b == null)
560       return "null";
561     return toStringBinary(b, 0, b.length);
562   }
563 
564   /**
565    * Converts the given byte buffer to a printable representation,
566    * from the index 0 (inclusive) to the limit (exclusive),
567    * regardless of the current position.
568    * The position and the other index parameters are not changed.
569    *
570    * @param buf a byte buffer
571    * @return a string representation of the buffer's binary contents
572    * @see #toBytes(ByteBuffer)
573    * @see #getBytes(ByteBuffer)
574    */
575   public static String toStringBinary(ByteBuffer buf) {
576     if (buf == null)
577       return "null";
578     if (buf.hasArray()) {
579       return toStringBinary(buf.array(), buf.arrayOffset(), buf.limit());
580     }
581     return toStringBinary(toBytes(buf));
582   }
583 
584   private static final char[] HEX_CHARS_UPPER = {
585     '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'
586   };
587 
588   /**
589    * Write a printable representation of a byte array. Non-printable
590    * characters are hex escaped in the format \\x%02X, eg:
591    * \x00 \x05 etc
592    *
593    * @param b array to write out
594    * @param off offset to start at
595    * @param len length to write
596    * @return string output
597    */
598   public static String toStringBinary(final byte [] b, int off, int len) {
599     StringBuilder result = new StringBuilder();
600     // Just in case we are passed a 'len' that is > buffer length...
601     if (off >= b.length) return result.toString();
602     if (off + len > b.length) len = b.length - off;
603     for (int i = off; i < off + len ; ++i ) {
604       int ch = b[i] & 0xFF;
605       if (ch >= ' ' && ch <= '~' && ch != '\\') {
606         result.append((char)ch);
607       } else {
608         result.append("\\x");
609         result.append(HEX_CHARS_UPPER[ch / 0x10]);
610         result.append(HEX_CHARS_UPPER[ch % 0x10]);
611       }
612     }
613     return result.toString();
614   }
615 
616   private static boolean isHexDigit(char c) {
617     return
618         (c >= 'A' && c <= 'F') ||
619         (c >= '0' && c <= '9');
620   }
621 
622   /**
623    * Takes a ASCII digit in the range A-F0-9 and returns
624    * the corresponding integer/ordinal value.
625    * @param ch  The hex digit.
626    * @return The converted hex value as a byte.
627    */
628   public static byte toBinaryFromHex(byte ch) {
629     if ( ch >= 'A' && ch <= 'F' )
630       return (byte) ((byte)10 + (byte) (ch - 'A'));
631     // else
632     return (byte) (ch - '0');
633   }
634 
635   public static byte [] toBytesBinary(String in) {
636     // this may be bigger than we need, but let's be safe.
637     byte [] b = new byte[in.length()];
638     int size = 0;
639     for (int i = 0; i < in.length(); ++i) {
640       char ch = in.charAt(i);
641       if (ch == '\\' && in.length() > i+1 && in.charAt(i+1) == 'x') {
642         // ok, take next 2 hex digits.
643         char hd1 = in.charAt(i+2);
644         char hd2 = in.charAt(i+3);
645 
646         // they need to be A-F0-9:
647         if (!isHexDigit(hd1) ||
648             !isHexDigit(hd2)) {
649           // bogus escape code, ignore:
650           continue;
651         }
652         // turn hex ASCII digit -> number
653         byte d = (byte) ((toBinaryFromHex((byte)hd1) << 4) + toBinaryFromHex((byte)hd2));
654 
655         b[size++] = d;
656         i += 3; // skip 3
657       } else {
658         b[size++] = (byte) ch;
659       }
660     }
661     // resize:
662     byte [] b2 = new byte[size];
663     System.arraycopy(b, 0, b2, 0, size);
664     return b2;
665   }
666 
667   /**
668    * Converts a string to a UTF-8 byte array.
669    * @param s string
670    * @return the byte array
671    */
672   public static byte[] toBytes(String s) {
673     return s.getBytes(UTF8_CHARSET);
674   }
675 
676   /**
677    * Convert a boolean to a byte array. True becomes -1
678    * and false becomes 0.
679    *
680    * @param b value
681    * @return <code>b</code> encoded in a byte array.
682    */
683   public static byte [] toBytes(final boolean b) {
684     return new byte[] { b ? (byte) -1 : (byte) 0 };
685   }
686 
687   /**
688    * Reverses {@link #toBytes(boolean)}
689    * @param b array
690    * @return True or false.
691    */
692   public static boolean toBoolean(final byte [] b) {
693     if (b.length != 1) {
694       throw new IllegalArgumentException("Array has wrong size: " + b.length);
695     }
696     return b[0] != (byte) 0;
697   }
698 
699   /**
700    * Convert a long value to a byte array using big-endian.
701    *
702    * @param val value to convert
703    * @return the byte array
704    */
705   public static byte[] toBytes(long val) {
706     byte [] b = new byte[8];
707     for (int i = 7; i > 0; i--) {
708       b[i] = (byte) val;
709       val >>>= 8;
710     }
711     b[0] = (byte) val;
712     return b;
713   }
714 
715   /**
716    * Converts a byte array to a long value. Reverses
717    * {@link #toBytes(long)}
718    * @param bytes array
719    * @return the long value
720    */
721   public static long toLong(byte[] bytes) {
722     return toLong(bytes, 0, SIZEOF_LONG);
723   }
724 
725   /**
726    * Converts a byte array to a long value. Assumes there will be
727    * {@link #SIZEOF_LONG} bytes available.
728    *
729    * @param bytes bytes
730    * @param offset offset
731    * @return the long value
732    */
733   public static long toLong(byte[] bytes, int offset) {
734     return toLong(bytes, offset, SIZEOF_LONG);
735   }
736 
737   /**
738    * Converts a byte array to a long value.
739    *
740    * @param bytes array of bytes
741    * @param offset offset into array
742    * @param length length of data (must be {@link #SIZEOF_LONG})
743    * @return the long value
744    * @throws IllegalArgumentException if length is not {@link #SIZEOF_LONG} or
745    * if there's not enough room in the array at the offset indicated.
746    */
747   public static long toLong(byte[] bytes, int offset, final int length) {
748     if (length != SIZEOF_LONG || offset + length > bytes.length) {
749       throw explainWrongLengthOrOffset(bytes, offset, length, SIZEOF_LONG);
750     }
751     return ConverterHolder.BEST_CONVERTER.toLong(bytes, offset, length);
752   }
753 
754   private static IllegalArgumentException
755     explainWrongLengthOrOffset(final byte[] bytes,
756                                final int offset,
757                                final int length,
758                                final int expectedLength) {
759     String reason;
760     if (length != expectedLength) {
761       reason = "Wrong length: " + length + ", expected " + expectedLength;
762     } else {
763      reason = "offset (" + offset + ") + length (" + length + ") exceed the"
764         + " capacity of the array: " + bytes.length;
765     }
766     return new IllegalArgumentException(reason);
767   }
768 
769   /**
770    * Put a long value out to the specified byte array position.
771    * @param bytes the byte array
772    * @param offset position in the array
773    * @param val long to write out
774    * @return incremented offset
775    * @throws IllegalArgumentException if the byte array given doesn't have
776    * enough room at the offset specified.
777    */
778   public static int putLong(byte[] bytes, int offset, long val) {
779     if (bytes.length - offset < SIZEOF_LONG) {
780       throw new IllegalArgumentException("Not enough room to put a long at"
781           + " offset " + offset + " in a " + bytes.length + " byte array");
782     }
783     return ConverterHolder.BEST_CONVERTER.putLong(bytes, offset, val);
784   }
785 
786   /**
787    * Put a long value out to the specified byte array position (Unsafe).
788    * @param bytes the byte array
789    * @param offset position in the array
790    * @param val long to write out
791    * @return incremented offset
792    */
793   public static int putLongUnsafe(byte[] bytes, int offset, long val)
794   {
795     if (UnsafeComparer.littleEndian) {
796       val = Long.reverseBytes(val);
797     }
798     UnsafeComparer.theUnsafe.putLong(bytes, (long) offset +
799       UnsafeComparer.BYTE_ARRAY_BASE_OFFSET , val);
800     return offset + SIZEOF_LONG;
801   }
802 
803   /**
804    * Presumes float encoded as IEEE 754 floating-point "single format"
805    * @param bytes byte array
806    * @return Float made from passed byte array.
807    */
808   public static float toFloat(byte [] bytes) {
809     return toFloat(bytes, 0);
810   }
811 
812   /**
813    * Presumes float encoded as IEEE 754 floating-point "single format"
814    * @param bytes array to convert
815    * @param offset offset into array
816    * @return Float made from passed byte array.
817    */
818   public static float toFloat(byte [] bytes, int offset) {
819     return Float.intBitsToFloat(toInt(bytes, offset, SIZEOF_INT));
820   }
821 
822   /**
823    * @param bytes byte array
824    * @param offset offset to write to
825    * @param f float value
826    * @return New offset in <code>bytes</code>
827    */
828   public static int putFloat(byte [] bytes, int offset, float f) {
829     return putInt(bytes, offset, Float.floatToRawIntBits(f));
830   }
831 
832   /**
833    * @param f float value
834    * @return the float represented as byte []
835    */
836   public static byte [] toBytes(final float f) {
837     // Encode it as int
838     return Bytes.toBytes(Float.floatToRawIntBits(f));
839   }
840 
841   /**
842    * @param bytes byte array
843    * @return Return double made from passed bytes.
844    */
845   public static double toDouble(final byte [] bytes) {
846     return toDouble(bytes, 0);
847   }
848 
849   /**
850    * @param bytes byte array
851    * @param offset offset where double is
852    * @return Return double made from passed bytes.
853    */
854   public static double toDouble(final byte [] bytes, final int offset) {
855     return Double.longBitsToDouble(toLong(bytes, offset, SIZEOF_LONG));
856   }
857 
858   /**
859    * @param bytes byte array
860    * @param offset offset to write to
861    * @param d value
862    * @return New offset into array <code>bytes</code>
863    */
864   public static int putDouble(byte [] bytes, int offset, double d) {
865     return putLong(bytes, offset, Double.doubleToLongBits(d));
866   }
867 
868   /**
869    * Serialize a double as the IEEE 754 double format output. The resultant
870    * array will be 8 bytes long.
871    *
872    * @param d value
873    * @return the double represented as byte []
874    */
875   public static byte [] toBytes(final double d) {
876     // Encode it as a long
877     return Bytes.toBytes(Double.doubleToRawLongBits(d));
878   }
879 
880   /**
881    * Convert an int value to a byte array.  Big-endian.  Same as what DataOutputStream.writeInt
882    * does.
883    *
884    * @param val value
885    * @return the byte array
886    */
887   public static byte[] toBytes(int val) {
888     byte [] b = new byte[4];
889     for(int i = 3; i > 0; i--) {
890       b[i] = (byte) val;
891       val >>>= 8;
892     }
893     b[0] = (byte) val;
894     return b;
895   }
896 
897   /**
898    * Converts a byte array to an int value
899    * @param bytes byte array
900    * @return the int value
901    */
902   public static int toInt(byte[] bytes) {
903     return toInt(bytes, 0, SIZEOF_INT);
904   }
905 
906   /**
907    * Converts a byte array to an int value
908    * @param bytes byte array
909    * @param offset offset into array
910    * @return the int value
911    */
912   public static int toInt(byte[] bytes, int offset) {
913     return toInt(bytes, offset, SIZEOF_INT);
914   }
915 
916   /**
917    * Converts a byte array to an int value
918    * @param bytes byte array
919    * @param offset offset into array
920    * @param length length of int (has to be {@link #SIZEOF_INT})
921    * @return the int value
922    * @throws IllegalArgumentException if length is not {@link #SIZEOF_INT} or
923    * if there's not enough room in the array at the offset indicated.
924    */
925   public static int toInt(byte[] bytes, int offset, final int length) {
926     if (length != SIZEOF_INT || offset + length > bytes.length) {
927       throw explainWrongLengthOrOffset(bytes, offset, length, SIZEOF_INT);
928     }
929     return ConverterHolder.BEST_CONVERTER.toInt(bytes, offset, length);
930   }
931 
932   /**
933    * Converts a byte array to an int value (Unsafe version)
934    * @param bytes byte array
935    * @param offset offset into array
936    * @return the int value
937    */
938   public static int toIntUnsafe(byte[] bytes, int offset) {
939     if (UnsafeComparer.littleEndian) {
940       return Integer.reverseBytes(UnsafeComparer.theUnsafe.getInt(bytes,
941         (long) offset + UnsafeComparer.BYTE_ARRAY_BASE_OFFSET));
942     } else {
943       return UnsafeComparer.theUnsafe.getInt(bytes,
944         (long) offset + UnsafeComparer.BYTE_ARRAY_BASE_OFFSET);
945     }
946   }
947 
948   /**
949    * Converts a byte array to an short value (Unsafe version)
950    * @param bytes byte array
951    * @param offset offset into array
952    * @return the short value
953    */
954   public static short toShortUnsafe(byte[] bytes, int offset) {
955     if (UnsafeComparer.littleEndian) {
956       return Short.reverseBytes(UnsafeComparer.theUnsafe.getShort(bytes,
957         (long) offset + UnsafeComparer.BYTE_ARRAY_BASE_OFFSET));
958     } else {
959       return UnsafeComparer.theUnsafe.getShort(bytes,
960         (long) offset + UnsafeComparer.BYTE_ARRAY_BASE_OFFSET);
961     }
962   }
963 
964   /**
965    * Converts a byte array to an long value (Unsafe version)
966    * @param bytes byte array
967    * @param offset offset into array
968    * @return the long value
969    */
970   public static long toLongUnsafe(byte[] bytes, int offset) {
971     if (UnsafeComparer.littleEndian) {
972       return Long.reverseBytes(UnsafeComparer.theUnsafe.getLong(bytes,
973         (long) offset + UnsafeComparer.BYTE_ARRAY_BASE_OFFSET));
974     } else {
975       return UnsafeComparer.theUnsafe.getLong(bytes,
976         (long) offset + UnsafeComparer.BYTE_ARRAY_BASE_OFFSET);
977     }
978   }
979 
980   /**
981    * Converts a byte array to an int value
982    * @param bytes byte array
983    * @param offset offset into array
984    * @param length how many bytes should be considered for creating int
985    * @return the int value
986    * @throws IllegalArgumentException if there's not enough room in the array at the offset
987    * indicated.
988    */
989   public static int readAsInt(byte[] bytes, int offset, final int length) {
990     if (offset + length > bytes.length) {
991       throw new IllegalArgumentException("offset (" + offset + ") + length (" + length
992           + ") exceed the" + " capacity of the array: " + bytes.length);
993     }
994     int n = 0;
995     for(int i = offset; i < (offset + length); i++) {
996       n <<= 8;
997       n ^= bytes[i] & 0xFF;
998     }
999     return n;
1000   }
1001 
1002   /**
1003    * Put an int value out to the specified byte array position.
1004    * @param bytes the byte array
1005    * @param offset position in the array
1006    * @param val int to write out
1007    * @return incremented offset
1008    * @throws IllegalArgumentException if the byte array given doesn't have
1009    * enough room at the offset specified.
1010    */
1011   public static int putInt(byte[] bytes, int offset, int val) {
1012     if (bytes.length - offset < SIZEOF_INT) {
1013       throw new IllegalArgumentException("Not enough room to put an int at"
1014           + " offset " + offset + " in a " + bytes.length + " byte array");
1015     }
1016     return ConverterHolder.BEST_CONVERTER.putInt(bytes, offset, val);
1017   }
1018 
1019   /**
1020    * Put an int value out to the specified byte array position (Unsafe).
1021    * @param bytes the byte array
1022    * @param offset position in the array
1023    * @param val int to write out
1024    * @return incremented offset
1025    */
1026   public static int putIntUnsafe(byte[] bytes, int offset, int val)
1027   {
1028     if (UnsafeComparer.littleEndian) {
1029       val = Integer.reverseBytes(val);
1030     }
1031     UnsafeComparer.theUnsafe.putInt(bytes, (long) offset +
1032       UnsafeComparer.BYTE_ARRAY_BASE_OFFSET , val);
1033     return offset + SIZEOF_INT;
1034   }
1035 
1036   /**
1037    * Convert a short value to a byte array of {@link #SIZEOF_SHORT} bytes long.
1038    * @param val value
1039    * @return the byte array
1040    */
1041   public static byte[] toBytes(short val) {
1042     byte[] b = new byte[SIZEOF_SHORT];
1043     b[1] = (byte) val;
1044     val >>= 8;
1045     b[0] = (byte) val;
1046     return b;
1047   }
1048 
1049   /**
1050    * Converts a byte array to a short value
1051    * @param bytes byte array
1052    * @return the short value
1053    */
1054   public static short toShort(byte[] bytes) {
1055     return toShort(bytes, 0, SIZEOF_SHORT);
1056   }
1057 
1058   /**
1059    * Converts a byte array to a short value
1060    * @param bytes byte array
1061    * @param offset offset into array
1062    * @return the short value
1063    */
1064   public static short toShort(byte[] bytes, int offset) {
1065     return toShort(bytes, offset, SIZEOF_SHORT);
1066   }
1067 
1068   /**
1069    * Converts a byte array to a short value
1070    * @param bytes byte array
1071    * @param offset offset into array
1072    * @param length length, has to be {@link #SIZEOF_SHORT}
1073    * @return the short value
1074    * @throws IllegalArgumentException if length is not {@link #SIZEOF_SHORT}
1075    * or if there's not enough room in the array at the offset indicated.
1076    */
1077   public static short toShort(byte[] bytes, int offset, final int length) {
1078     if (length != SIZEOF_SHORT || offset + length > bytes.length) {
1079       throw explainWrongLengthOrOffset(bytes, offset, length, SIZEOF_SHORT);
1080     }
1081     if (UNSAFE_UNALIGNED) {
1082       return ConverterHolder.BEST_CONVERTER.toShort(bytes, offset, length);
1083     } else {
1084       short n = 0;
1085       n = (short) (n ^ (bytes[offset] & 0xFF));
1086       n = (short) (n << 8);
1087       n = (short) (n ^ (bytes[offset + 1] & 0xFF));
1088       return n;
1089     }
1090   }
1091 
1092   /**
1093    * Returns a new byte array, copied from the given {@code buf},
1094    * from the position (inclusive) to the limit (exclusive).
1095    * The position and the other index parameters are not changed.
1096    *
1097    * @param buf a byte buffer
1098    * @return the byte array
1099    * @see #toBytes(ByteBuffer)
1100    */
1101   public static byte[] getBytes(ByteBuffer buf) {
1102     return readBytes(buf.duplicate());
1103   }
1104 
1105   /**
1106    * Put a short value out to the specified byte array position.
1107    * @param bytes the byte array
1108    * @param offset position in the array
1109    * @param val short to write out
1110    * @return incremented offset
1111    * @throws IllegalArgumentException if the byte array given doesn't have
1112    * enough room at the offset specified.
1113    */
1114   public static int putShort(byte[] bytes, int offset, short val) {
1115     if (bytes.length - offset < SIZEOF_SHORT) {
1116       throw new IllegalArgumentException("Not enough room to put a short at"
1117           + " offset " + offset + " in a " + bytes.length + " byte array");
1118     }
1119     return ConverterHolder.BEST_CONVERTER.putShort(bytes, offset, val);
1120   }
1121 
1122   /**
1123    * Put a short value out to the specified byte array position (Unsafe).
1124    * @param bytes the byte array
1125    * @param offset position in the array
1126    * @param val short to write out
1127    * @return incremented offset
1128    */
1129   public static int putShortUnsafe(byte[] bytes, int offset, short val)
1130   {
1131     if (UnsafeComparer.littleEndian) {
1132       val = Short.reverseBytes(val);
1133     }
1134     UnsafeComparer.theUnsafe.putShort(bytes, (long) offset +
1135       UnsafeComparer.BYTE_ARRAY_BASE_OFFSET , val);
1136     return offset + SIZEOF_SHORT;
1137   }
1138 
1139   /**
1140    * Put an int value as short out to the specified byte array position. Only the lower 2 bytes of
1141    * the short will be put into the array. The caller of the API need to make sure they will not
1142    * loose the value by doing so. This is useful to store an unsigned short which is represented as
1143    * int in other parts.
1144    * @param bytes the byte array
1145    * @param offset position in the array
1146    * @param val value to write out
1147    * @return incremented offset
1148    * @throws IllegalArgumentException if the byte array given doesn't have
1149    * enough room at the offset specified.
1150    */
1151   public static int putAsShort(byte[] bytes, int offset, int val) {
1152     if (bytes.length - offset < SIZEOF_SHORT) {
1153       throw new IllegalArgumentException("Not enough room to put a short at"
1154           + " offset " + offset + " in a " + bytes.length + " byte array");
1155     }
1156     bytes[offset+1] = (byte) val;
1157     val >>= 8;
1158     bytes[offset] = (byte) val;
1159     return offset + SIZEOF_SHORT;
1160   }
1161 
1162   /**
1163    * Convert a BigDecimal value to a byte array
1164    *
1165    * @param val
1166    * @return the byte array
1167    */
1168   public static byte[] toBytes(BigDecimal val) {
1169     byte[] valueBytes = val.unscaledValue().toByteArray();
1170     byte[] result = new byte[valueBytes.length + SIZEOF_INT];
1171     int offset = putInt(result, 0, val.scale());
1172     putBytes(result, offset, valueBytes, 0, valueBytes.length);
1173     return result;
1174   }
1175 
1176 
1177   /**
1178    * Converts a byte array to a BigDecimal
1179    *
1180    * @param bytes
1181    * @return the char value
1182    */
1183   public static BigDecimal toBigDecimal(byte[] bytes) {
1184     return toBigDecimal(bytes, 0, bytes.length);
1185   }
1186 
1187   /**
1188    * Converts a byte array to a BigDecimal value
1189    *
1190    * @param bytes
1191    * @param offset
1192    * @param length
1193    * @return the char value
1194    */
1195   public static BigDecimal toBigDecimal(byte[] bytes, int offset, final int length) {
1196     if (bytes == null || length < SIZEOF_INT + 1 ||
1197       (offset + length > bytes.length)) {
1198       return null;
1199     }
1200 
1201     int scale = toInt(bytes, offset);
1202     byte[] tcBytes = new byte[length - SIZEOF_INT];
1203     System.arraycopy(bytes, offset + SIZEOF_INT, tcBytes, 0, length - SIZEOF_INT);
1204     return new BigDecimal(new BigInteger(tcBytes), scale);
1205   }
1206 
1207   /**
1208    * Put a BigDecimal value out to the specified byte array position.
1209    *
1210    * @param bytes  the byte array
1211    * @param offset position in the array
1212    * @param val    BigDecimal to write out
1213    * @return incremented offset
1214    */
1215   public static int putBigDecimal(byte[] bytes, int offset, BigDecimal val) {
1216     if (bytes == null) {
1217       return offset;
1218     }
1219 
1220     byte[] valueBytes = val.unscaledValue().toByteArray();
1221     byte[] result = new byte[valueBytes.length + SIZEOF_INT];
1222     offset = putInt(result, offset, val.scale());
1223     return putBytes(result, offset, valueBytes, 0, valueBytes.length);
1224   }
1225 
1226   /**
1227    * @param vint Integer to make a vint of.
1228    * @return Vint as bytes array.
1229    */
1230   public static byte [] vintToBytes(final long vint) {
1231     long i = vint;
1232     int size = WritableUtils.getVIntSize(i);
1233     byte [] result = new byte[size];
1234     int offset = 0;
1235     if (i >= -112 && i <= 127) {
1236       result[offset] = (byte) i;
1237       return result;
1238     }
1239 
1240     int len = -112;
1241     if (i < 0) {
1242       i ^= -1L; // take one's complement'
1243       len = -120;
1244     }
1245 
1246     long tmp = i;
1247     while (tmp != 0) {
1248       tmp = tmp >> 8;
1249       len--;
1250     }
1251 
1252     result[offset++] = (byte) len;
1253 
1254     len = (len < -120) ? -(len + 120) : -(len + 112);
1255 
1256     for (int idx = len; idx != 0; idx--) {
1257       int shiftbits = (idx - 1) * 8;
1258       long mask = 0xFFL << shiftbits;
1259       result[offset++] = (byte)((i & mask) >> shiftbits);
1260     }
1261     return result;
1262   }
1263 
1264   /**
1265    * @param buffer buffer to convert
1266    * @return vint bytes as an integer.
1267    */
1268   public static long bytesToVint(final byte [] buffer) {
1269     int offset = 0;
1270     byte firstByte = buffer[offset++];
1271     int len = WritableUtils.decodeVIntSize(firstByte);
1272     if (len == 1) {
1273       return firstByte;
1274     }
1275     long i = 0;
1276     for (int idx = 0; idx < len-1; idx++) {
1277       byte b = buffer[offset++];
1278       i = i << 8;
1279       i = i | (b & 0xFF);
1280     }
1281     return (WritableUtils.isNegativeVInt(firstByte) ? ~i : i);
1282   }
1283 
1284   /**
1285    * Reads a zero-compressed encoded long from input buffer and returns it.
1286    * @param buffer Binary array
1287    * @param offset Offset into array at which vint begins.
1288    * @throws java.io.IOException e
1289    * @return deserialized long from buffer.
1290    * @deprecated since 0.98.12. Use {@link #readAsVLong(byte[],int)} instead.
1291    * @see #readAsVLong(byte[], int)
1292    * @see <a href="https://issues.apache.org/jira/browse/HBASE-6919">HBASE-6919</a>
1293    */
1294   @Deprecated
1295   public static long readVLong(final byte [] buffer, final int offset)
1296   throws IOException {
1297     return readAsVLong(buffer, offset);
1298   }
1299 
1300   /**
1301    * Reads a zero-compressed encoded long from input buffer and returns it.
1302    * @param buffer Binary array
1303    * @param offset Offset into array at which vint begins.
1304    * @return deserialized long from buffer.
1305    */
1306   public static long readAsVLong(final byte [] buffer, final int offset) {
1307     byte firstByte = buffer[offset];
1308     int len = WritableUtils.decodeVIntSize(firstByte);
1309     if (len == 1) {
1310       return firstByte;
1311     }
1312     long i = 0;
1313     for (int idx = 0; idx < len-1; idx++) {
1314       byte b = buffer[offset + 1 + idx];
1315       i = i << 8;
1316       i = i | (b & 0xFF);
1317     }
1318     return (WritableUtils.isNegativeVInt(firstByte) ? ~i : i);
1319   }
1320 
1321   /**
1322    * @param left left operand
1323    * @param right right operand
1324    * @return 0 if equal, &lt; 0 if left is less than right, etc.
1325    */
1326   public static int compareTo(final byte [] left, final byte [] right) {
1327     return LexicographicalComparerHolder.BEST_COMPARER.
1328       compareTo(left, 0, left.length, right, 0, right.length);
1329   }
1330 
1331   /**
1332    * Lexicographically compare two arrays.
1333    *
1334    * @param buffer1 left operand
1335    * @param buffer2 right operand
1336    * @param offset1 Where to start comparing in the left buffer
1337    * @param offset2 Where to start comparing in the right buffer
1338    * @param length1 How much to compare from the left buffer
1339    * @param length2 How much to compare from the right buffer
1340    * @return 0 if equal, &lt; 0 if left is less than right, etc.
1341    */
1342   public static int compareTo(byte[] buffer1, int offset1, int length1,
1343       byte[] buffer2, int offset2, int length2) {
1344     return LexicographicalComparerHolder.BEST_COMPARER.
1345       compareTo(buffer1, offset1, length1, buffer2, offset2, length2);
1346   }
1347 
1348   interface Comparer<T> {
1349     int compareTo(
1350       T buffer1, int offset1, int length1, T buffer2, int offset2, int length2
1351     );
1352   }
1353 
1354   static abstract class Converter {
1355     abstract long toLong(byte[] bytes, int offset, int length);
1356     abstract int putLong(byte[] bytes, int offset, long val);
1357 
1358     abstract int toInt(byte[] bytes, int offset, final int length);
1359     abstract int putInt(byte[] bytes, int offset, int val);
1360 
1361     abstract short toShort(byte[] bytes, int offset, final int length);
1362     abstract int putShort(byte[] bytes, int offset, short val);
1363 
1364   }
1365 
1366   @InterfaceAudience.Private
1367   static Comparer<byte[]> lexicographicalComparerJavaImpl() {
1368     return LexicographicalComparerHolder.PureJavaComparer.INSTANCE;
1369   }
1370 
1371   static class ConverterHolder {
1372     static final String UNSAFE_CONVERTER_NAME =
1373             ConverterHolder.class.getName() + "$UnsafeConverter";
1374 
1375     static final Converter BEST_CONVERTER = getBestConverter();
1376     /**
1377      * Returns the Unsafe-using Converter, or falls back to the pure-Java
1378      * implementation if unable to do so.
1379      */
1380     static Converter getBestConverter() {
1381       try {
1382         Class<?> theClass = Class.forName(UNSAFE_CONVERTER_NAME);
1383 
1384         // yes, UnsafeComparer does implement Comparer<byte[]>
1385         @SuppressWarnings("unchecked")
1386         Converter converter = (Converter) theClass.getConstructor().newInstance();
1387         return converter;
1388       } catch (Throwable t) { // ensure we really catch *everything*
1389         return PureJavaConverter.INSTANCE;
1390       }
1391     }
1392 
1393     protected static final class PureJavaConverter extends Converter {
1394       static final PureJavaConverter INSTANCE = new PureJavaConverter();
1395 
1396       private PureJavaConverter() {}
1397 
1398       @Override
1399       long toLong(byte[] bytes, int offset, int length) {
1400         long l = 0;
1401         for(int i = offset; i < offset + length; i++) {
1402           l <<= 8;
1403           l ^= bytes[i] & 0xFF;
1404         }
1405         return l;
1406       }
1407 
1408       @Override
1409       int putLong(byte[] bytes, int offset, long val) {
1410         for(int i = offset + 7; i > offset; i--) {
1411           bytes[i] = (byte) val;
1412           val >>>= 8;
1413         }
1414         bytes[offset] = (byte) val;
1415         return offset + SIZEOF_LONG;
1416       }
1417 
1418       @Override
1419       int toInt(byte[] bytes, int offset, int length) {
1420         int n = 0;
1421         for(int i = offset; i < (offset + length); i++) {
1422           n <<= 8;
1423           n ^= bytes[i] & 0xFF;
1424         }
1425         return n;
1426       }
1427 
1428       @Override
1429       int putInt(byte[] bytes, int offset, int val) {
1430         for(int i= offset + 3; i > offset; i--) {
1431           bytes[i] = (byte) val;
1432           val >>>= 8;
1433         }
1434         bytes[offset] = (byte) val;
1435         return offset + SIZEOF_INT;
1436       }
1437 
1438       @Override
1439       short toShort(byte[] bytes, int offset, int length) {
1440         short n = 0;
1441         n = (short) ((n ^ bytes[offset]) & 0xFF);
1442         n = (short) (n << 8);
1443         n ^= (short) (bytes[offset+1] & 0xFF);
1444         return n;
1445       }
1446 
1447       @Override
1448       int putShort(byte[] bytes, int offset, short val) {
1449         bytes[offset+1] = (byte) val;
1450         val >>= 8;
1451         bytes[offset] = (byte) val;
1452         return offset + SIZEOF_SHORT;
1453       }
1454     }
1455 
1456     protected static final class UnsafeConverter extends Converter {
1457 
1458       static final Unsafe theUnsafe;
1459 
1460       public UnsafeConverter() {}
1461 
1462       static {
1463         if (UNSAFE_UNALIGNED) {
1464           theUnsafe = UnsafeAccess.theUnsafe;
1465         } else {
1466           // It doesn't matter what we throw;
1467           // it's swallowed in getBestComparer().
1468           throw new Error();
1469         }
1470 
1471         // sanity check - this should never fail
1472         if (theUnsafe.arrayIndexScale(byte[].class) != 1) {
1473           throw new AssertionError();
1474         }
1475       }
1476 
1477       @Override
1478       long toLong(byte[] bytes, int offset, int length) {
1479         return UnsafeAccess.toLong(bytes, offset);
1480       }
1481 
1482       @Override
1483       int putLong(byte[] bytes, int offset, long val) {
1484         return UnsafeAccess.putLong(bytes, offset, val);
1485       }
1486 
1487       @Override
1488       int toInt(byte[] bytes, int offset, int length) {
1489         return UnsafeAccess.toInt(bytes, offset);
1490       }
1491 
1492       @Override
1493       int putInt(byte[] bytes, int offset, int val) {
1494         return UnsafeAccess.putInt(bytes, offset, val);
1495       }
1496 
1497       @Override
1498       short toShort(byte[] bytes, int offset, int length) {
1499         return UnsafeAccess.toShort(bytes, offset);
1500       }
1501 
1502       @Override
1503       int putShort(byte[] bytes, int offset, short val) {
1504         return UnsafeAccess.putShort(bytes, offset, val);
1505       }
1506     }
1507   }
1508 
1509   /**
1510    * Provides a lexicographical comparer implementation; either a Java
1511    * implementation or a faster implementation based on {@link Unsafe}.
1512    *
1513    * <p>Uses reflection to gracefully fall back to the Java implementation if
1514    * {@code Unsafe} isn't available.
1515    */
1516   @InterfaceAudience.Private
1517   static class LexicographicalComparerHolder {
1518     static final String UNSAFE_COMPARER_NAME =
1519         LexicographicalComparerHolder.class.getName() + "$UnsafeComparer";
1520 
1521     static final Comparer<byte[]> BEST_COMPARER = getBestComparer();
1522     /**
1523      * Returns the Unsafe-using Comparer, or falls back to the pure-Java
1524      * implementation if unable to do so.
1525      */
1526     static Comparer<byte[]> getBestComparer() {
1527       try {
1528         Class<?> theClass = Class.forName(UNSAFE_COMPARER_NAME);
1529 
1530         // yes, UnsafeComparer does implement Comparer<byte[]>
1531         @SuppressWarnings("unchecked")
1532         Comparer<byte[]> comparer =
1533           (Comparer<byte[]>) theClass.getEnumConstants()[0];
1534         return comparer;
1535       } catch (Throwable t) { // ensure we really catch *everything*
1536         return lexicographicalComparerJavaImpl();
1537       }
1538     }
1539 
1540     enum PureJavaComparer implements Comparer<byte[]> {
1541       INSTANCE;
1542 
1543       @Override
1544       public int compareTo(byte[] buffer1, int offset1, int length1,
1545           byte[] buffer2, int offset2, int length2) {
1546         // Short circuit equal case
1547         if (buffer1 == buffer2 &&
1548             offset1 == offset2 &&
1549             length1 == length2) {
1550           return 0;
1551         }
1552         // Bring WritableComparator code local
1553         int end1 = offset1 + length1;
1554         int end2 = offset2 + length2;
1555         for (int i = offset1, j = offset2; i < end1 && j < end2; i++, j++) {
1556           int a = (buffer1[i] & 0xff);
1557           int b = (buffer2[j] & 0xff);
1558           if (a != b) {
1559             return a - b;
1560           }
1561         }
1562         return length1 - length2;
1563       }
1564     }
1565 
1566     @InterfaceAudience.Private
1567     enum UnsafeComparer implements Comparer<byte[]> {
1568       INSTANCE;
1569 
1570       static final Unsafe theUnsafe;
1571 
1572       /** The offset to the first element in a byte array. */
1573       static final int BYTE_ARRAY_BASE_OFFSET;
1574 
1575       static {
1576         if (UNSAFE_UNALIGNED) {
1577           theUnsafe = UnsafeAccess.theUnsafe;
1578         } else {
1579           // It doesn't matter what we throw;
1580           // it's swallowed in getBestComparer().
1581           throw new Error();
1582         }
1583 
1584         BYTE_ARRAY_BASE_OFFSET = theUnsafe.arrayBaseOffset(byte[].class);
1585 
1586         // sanity check - this should never fail
1587         if (theUnsafe.arrayIndexScale(byte[].class) != 1) {
1588           throw new AssertionError();
1589         }
1590       }
1591 
1592       static final boolean littleEndian =
1593         ByteOrder.nativeOrder().equals(ByteOrder.LITTLE_ENDIAN);
1594 
1595       /**
1596        * Returns true if x1 is less than x2, when both values are treated as
1597        * unsigned long.
1598        * Both values are passed as is read by Unsafe. When platform is Little Endian, have to
1599        * convert to corresponding Big Endian value and then do compare. We do all writes in
1600        * Big Endian format.
1601        */
1602       static boolean lessThanUnsignedLong(long x1, long x2) {
1603         if (littleEndian) {
1604           x1 = Long.reverseBytes(x1);
1605           x2 = Long.reverseBytes(x2);
1606         }
1607         return (x1 + Long.MIN_VALUE) < (x2 + Long.MIN_VALUE);
1608       }
1609 
1610       /**
1611        * Returns true if x1 is less than x2, when both values are treated as
1612        * unsigned int.
1613        * Both values are passed as is read by Unsafe. When platform is Little Endian, have to
1614        * convert to corresponding Big Endian value and then do compare. We do all writes in
1615        * Big Endian format.
1616        */
1617       static boolean lessThanUnsignedInt(int x1, int x2) {
1618         if (littleEndian) {
1619           x1 = Integer.reverseBytes(x1);
1620           x2 = Integer.reverseBytes(x2);
1621         }
1622         return (x1 & 0xffffffffL) < (x2 & 0xffffffffL);
1623       }
1624 
1625       /**
1626        * Returns true if x1 is less than x2, when both values are treated as
1627        * unsigned short.
1628        * Both values are passed as is read by Unsafe. When platform is Little Endian, have to
1629        * convert to corresponding Big Endian value and then do compare. We do all writes in
1630        * Big Endian format.
1631        */
1632       static boolean lessThanUnsignedShort(short x1, short x2) {
1633         if (littleEndian) {
1634           x1 = Short.reverseBytes(x1);
1635           x2 = Short.reverseBytes(x2);
1636         }
1637         return (x1 & 0xffff) < (x2 & 0xffff);
1638       }
1639 
1640       /**
1641        * Checks if Unsafe is available
1642        * @return true, if available, false - otherwise
1643        */
1644       public static boolean isAvailable()
1645       {
1646         return theUnsafe != null;
1647       }
1648 
1649       /**
1650        * Lexicographically compare two arrays.
1651        *
1652        * @param buffer1 left operand
1653        * @param buffer2 right operand
1654        * @param offset1 Where to start comparing in the left buffer
1655        * @param offset2 Where to start comparing in the right buffer
1656        * @param length1 How much to compare from the left buffer
1657        * @param length2 How much to compare from the right buffer
1658        * @return 0 if equal, < 0 if left is less than right, etc.
1659        */
1660       @Override
1661       public int compareTo(byte[] buffer1, int offset1, int length1,
1662           byte[] buffer2, int offset2, int length2) {
1663 
1664         // Short circuit equal case
1665         if (buffer1 == buffer2 &&
1666             offset1 == offset2 &&
1667             length1 == length2) {
1668           return 0;
1669         }
1670         final int stride = 8;
1671         final int minLength = Math.min(length1, length2);
1672         int strideLimit = minLength & ~(stride - 1);
1673         final long offset1Adj = (long) offset1 + BYTE_ARRAY_BASE_OFFSET;
1674         final long offset2Adj = (long) offset2 + BYTE_ARRAY_BASE_OFFSET;
1675         int i;
1676 
1677         /*
1678          * Compare 8 bytes at a time. Benchmarking on x86 shows a stride of 8 bytes is no slower
1679          * than 4 bytes even on 32-bit. On the other hand, it is substantially faster on 64-bit.
1680          */
1681         for (i = 0; i < strideLimit; i += stride) {
1682           long lw = theUnsafe.getLong(buffer1, offset1Adj + (long) i);
1683           long rw = theUnsafe.getLong(buffer2, offset2Adj + (long) i);
1684           if (lw != rw) {
1685             if (!littleEndian) {
1686               return ((lw + Long.MIN_VALUE) < (rw + Long.MIN_VALUE)) ? -1 : 1;
1687             }
1688 
1689             /*
1690              * We want to compare only the first index where left[index] != right[index]. This
1691              * corresponds to the least significant nonzero byte in lw ^ rw, since lw and rw are
1692              * little-endian. Long.numberOfTrailingZeros(diff) tells us the least significant
1693              * nonzero bit, and zeroing out the first three bits of L.nTZ gives us the shift to get
1694              * that least significant nonzero byte. This comparison logic is based on UnsignedBytes
1695              * comparator from guava v21
1696              */
1697             int n = Long.numberOfTrailingZeros(lw ^ rw) & ~0x7;
1698             return ((int) ((lw >>> n) & 0xFF)) - ((int) ((rw >>> n) & 0xFF));
1699           }
1700         }
1701 
1702         // The epilogue to cover the last (minLength % stride) elements.
1703         for (; i < minLength; i++) {
1704           int a = (buffer1[offset1 + i] & 0xFF);
1705           int b = (buffer2[offset2 + i] & 0xFF);
1706           if (a != b) {
1707             return a - b;
1708           }
1709         }
1710         return length1 - length2;
1711       }
1712     }
1713   }
1714 
1715   /**
1716    * @param left left operand
1717    * @param right right operand
1718    * @return True if equal
1719    */
1720   public static boolean equals(final byte [] left, final byte [] right) {
1721     // Could use Arrays.equals?
1722     //noinspection SimplifiableConditionalExpression
1723     if (left == right) return true;
1724     if (left == null || right == null) return false;
1725     if (left.length != right.length) return false;
1726     if (left.length == 0) return true;
1727 
1728     // Since we're often comparing adjacent sorted data,
1729     // it's usual to have equal arrays except for the very last byte
1730     // so check that first
1731     if (left[left.length - 1] != right[right.length - 1]) return false;
1732 
1733     return compareTo(left, right) == 0;
1734   }
1735 
1736   public static boolean equals(final byte[] left, int leftOffset, int leftLen,
1737                                final byte[] right, int rightOffset, int rightLen) {
1738     // short circuit case
1739     if (left == right &&
1740         leftOffset == rightOffset &&
1741         leftLen == rightLen) {
1742       return true;
1743     }
1744     // different lengths fast check
1745     if (leftLen != rightLen) {
1746       return false;
1747     }
1748     if (leftLen == 0) {
1749       return true;
1750     }
1751 
1752     // Since we're often comparing adjacent sorted data,
1753     // it's usual to have equal arrays except for the very last byte
1754     // so check that first
1755     if (left[leftOffset + leftLen - 1] != right[rightOffset + rightLen - 1]) return false;
1756 
1757     return LexicographicalComparerHolder.BEST_COMPARER.
1758       compareTo(left, leftOffset, leftLen, right, rightOffset, rightLen) == 0;
1759   }
1760 
1761 
1762   /**
1763    * @param a left operand
1764    * @param buf right operand
1765    * @return True if equal
1766    */
1767   public static boolean equals(byte[] a, ByteBuffer buf) {
1768     if (a == null) return buf == null;
1769     if (buf == null) return false;
1770     if (a.length != buf.remaining()) return false;
1771 
1772     // Thou shalt not modify the original byte buffer in what should be read only operations.
1773     ByteBuffer b = buf.duplicate();
1774     for (byte anA : a) {
1775       if (anA != b.get()) {
1776         return false;
1777       }
1778     }
1779     return true;
1780   }
1781 
1782 
1783   /**
1784    * Return true if the byte array on the right is a prefix of the byte
1785    * array on the left.
1786    */
1787   public static boolean startsWith(byte[] bytes, byte[] prefix) {
1788     return bytes != null && prefix != null &&
1789       bytes.length >= prefix.length &&
1790       LexicographicalComparerHolder.BEST_COMPARER.
1791         compareTo(bytes, 0, prefix.length, prefix, 0, prefix.length) == 0;
1792   }
1793 
1794   /**
1795    * @param b bytes to hash
1796    * @return Runs {@link WritableComparator#hashBytes(byte[], int)} on the
1797    * passed in array.  This method is what {@link org.apache.hadoop.io.Text} and
1798    * {@link org.apache.hadoop.hbase.io.ImmutableBytesWritable} use calculating hash code.
1799    */
1800   public static int hashCode(final byte [] b) {
1801     return hashCode(b, b.length);
1802   }
1803 
1804   /**
1805    * @param b value
1806    * @param length length of the value
1807    * @return Runs {@link WritableComparator#hashBytes(byte[], int)} on the
1808    * passed in array.  This method is what {@link org.apache.hadoop.io.Text} and
1809    * {@link org.apache.hadoop.hbase.io.ImmutableBytesWritable} use calculating hash code.
1810    */
1811   public static int hashCode(final byte [] b, final int length) {
1812     return WritableComparator.hashBytes(b, length);
1813   }
1814 
1815   /**
1816    * @param b bytes to hash
1817    * @return A hash of <code>b</code> as an Integer that can be used as key in
1818    * Maps.
1819    */
1820   public static Integer mapKey(final byte [] b) {
1821     return hashCode(b);
1822   }
1823 
1824   /**
1825    * @param b bytes to hash
1826    * @param length length to hash
1827    * @return A hash of <code>b</code> as an Integer that can be used as key in
1828    * Maps.
1829    */
1830   public static Integer mapKey(final byte [] b, final int length) {
1831     return hashCode(b, length);
1832   }
1833 
1834   /**
1835    * @param a lower half
1836    * @param b upper half
1837    * @return New array that has a in lower half and b in upper half.
1838    */
1839   public static byte [] add(final byte [] a, final byte [] b) {
1840     return add(a, b, EMPTY_BYTE_ARRAY);
1841   }
1842 
1843   /**
1844    * @param a first third
1845    * @param b second third
1846    * @param c third third
1847    * @return New array made from a, b and c
1848    */
1849   public static byte [] add(final byte [] a, final byte [] b, final byte [] c) {
1850     byte [] result = new byte[a.length + b.length + c.length];
1851     System.arraycopy(a, 0, result, 0, a.length);
1852     System.arraycopy(b, 0, result, a.length, b.length);
1853     System.arraycopy(c, 0, result, a.length + b.length, c.length);
1854     return result;
1855   }
1856 
1857   /**
1858    * @param arrays all the arrays to concatenate together.
1859    * @return New array made from the concatenation of the given arrays.
1860    */
1861   public static byte [] add(final byte [][] arrays) {
1862     int length = 0;
1863     for (int i = 0; i < arrays.length; i++) {
1864       length += arrays[i].length;
1865     }
1866     byte [] result = new byte[length];
1867     int index = 0;
1868     for (int i = 0; i < arrays.length; i++) {
1869       System.arraycopy(arrays[i], 0, result, index, arrays[i].length);
1870       index += arrays[i].length;
1871     }
1872     return result;
1873   }
1874 
1875   /**
1876    * @param a array
1877    * @param length amount of bytes to grab
1878    * @return First <code>length</code> bytes from <code>a</code>
1879    */
1880   public static byte [] head(final byte [] a, final int length) {
1881     if (a.length < length) {
1882       return null;
1883     }
1884     byte [] result = new byte[length];
1885     System.arraycopy(a, 0, result, 0, length);
1886     return result;
1887   }
1888 
1889   /**
1890    * @param a array
1891    * @param length amount of bytes to snarf
1892    * @return Last <code>length</code> bytes from <code>a</code>
1893    */
1894   public static byte [] tail(final byte [] a, final int length) {
1895     if (a.length < length) {
1896       return null;
1897     }
1898     byte [] result = new byte[length];
1899     System.arraycopy(a, a.length - length, result, 0, length);
1900     return result;
1901   }
1902 
1903   /**
1904    * @param a array
1905    * @param length new array size
1906    * @return Value in <code>a</code> plus <code>length</code> prepended 0 bytes
1907    */
1908   public static byte [] padHead(final byte [] a, final int length) {
1909     byte [] padding = new byte[length];
1910     for (int i = 0; i < length; i++) {
1911       padding[i] = 0;
1912     }
1913     return add(padding,a);
1914   }
1915 
1916   /**
1917    * @param a array
1918    * @param length new array size
1919    * @return Value in <code>a</code> plus <code>length</code> appended 0 bytes
1920    */
1921   public static byte [] padTail(final byte [] a, final int length) {
1922     byte [] padding = new byte[length];
1923     for (int i = 0; i < length; i++) {
1924       padding[i] = 0;
1925     }
1926     return add(a,padding);
1927   }
1928 
1929   /**
1930    * Split passed range.  Expensive operation relatively.  Uses BigInteger math.
1931    * Useful splitting ranges for MapReduce jobs.
1932    * @param a Beginning of range
1933    * @param b End of range
1934    * @param num Number of times to split range.  Pass 1 if you want to split
1935    * the range in two; i.e. one split.
1936    * @return Array of dividing values
1937    */
1938   public static byte [][] split(final byte [] a, final byte [] b, final int num) {
1939     return split(a, b, false, num);
1940   }
1941 
1942   /**
1943    * Split passed range.  Expensive operation relatively.  Uses BigInteger math.
1944    * Useful splitting ranges for MapReduce jobs.
1945    * @param a Beginning of range
1946    * @param b End of range
1947    * @param inclusive Whether the end of range is prefix-inclusive or is
1948    * considered an exclusive boundary.  Automatic splits are generally exclusive
1949    * and manual splits with an explicit range utilize an inclusive end of range.
1950    * @param num Number of times to split range.  Pass 1 if you want to split
1951    * the range in two; i.e. one split.
1952    * @return Array of dividing values
1953    */
1954   public static byte[][] split(final byte[] a, final byte[] b,
1955       boolean inclusive, final int num) {
1956     byte[][] ret = new byte[num + 2][];
1957     int i = 0;
1958     Iterable<byte[]> iter = iterateOnSplits(a, b, inclusive, num);
1959     if (iter == null)
1960       return null;
1961     for (byte[] elem : iter) {
1962       ret[i++] = elem;
1963     }
1964     return ret;
1965   }
1966 
1967   /**
1968    * Iterate over keys within the passed range, splitting at an [a,b) boundary.
1969    */
1970   public static Iterable<byte[]> iterateOnSplits(final byte[] a,
1971       final byte[] b, final int num)
1972   {
1973     return iterateOnSplits(a, b, false, num);
1974   }
1975 
1976   /**
1977    * Iterate over keys within the passed range.
1978    */
1979   public static Iterable<byte[]> iterateOnSplits(
1980       final byte[] a, final byte[]b, boolean inclusive, final int num)
1981   {
1982     byte [] aPadded;
1983     byte [] bPadded;
1984     if (a.length < b.length) {
1985       aPadded = padTail(a, b.length - a.length);
1986       bPadded = b;
1987     } else if (b.length < a.length) {
1988       aPadded = a;
1989       bPadded = padTail(b, a.length - b.length);
1990     } else {
1991       aPadded = a;
1992       bPadded = b;
1993     }
1994     if (compareTo(aPadded,bPadded) >= 0) {
1995       throw new IllegalArgumentException("b <= a");
1996     }
1997     if (num <= 0) {
1998       throw new IllegalArgumentException("num cannot be <= 0");
1999     }
2000     byte [] prependHeader = {1, 0};
2001     final BigInteger startBI = new BigInteger(add(prependHeader, aPadded));
2002     final BigInteger stopBI = new BigInteger(add(prependHeader, bPadded));
2003     BigInteger diffBI = stopBI.subtract(startBI);
2004     if (inclusive) {
2005       diffBI = diffBI.add(BigInteger.ONE);
2006     }
2007     final BigInteger splitsBI = BigInteger.valueOf(num + 1);
2008     //when diffBI < splitBI, use an additional byte to increase diffBI
2009     if(diffBI.compareTo(splitsBI) < 0) {
2010       byte[] aPaddedAdditional = new byte[aPadded.length+1];
2011       byte[] bPaddedAdditional = new byte[bPadded.length+1];
2012       for (int i = 0; i < aPadded.length; i++){
2013         aPaddedAdditional[i] = aPadded[i];
2014       }
2015       for (int j = 0; j < bPadded.length; j++){
2016         bPaddedAdditional[j] = bPadded[j];
2017       }
2018       aPaddedAdditional[aPadded.length] = 0;
2019       bPaddedAdditional[bPadded.length] = 0;
2020       return iterateOnSplits(aPaddedAdditional, bPaddedAdditional, inclusive,  num);
2021     }
2022     final BigInteger intervalBI;
2023     try {
2024       intervalBI = diffBI.divide(splitsBI);
2025     } catch(Exception e) {
2026       LOG.error("Exception caught during division", e);
2027       return null;
2028     }
2029 
2030     final Iterator<byte[]> iterator = new Iterator<byte[]>() {
2031       private int i = -1;
2032 
2033       @Override
2034       public boolean hasNext() {
2035         return i < num+1;
2036       }
2037 
2038       @Override
2039       public byte[] next() {
2040         i++;
2041         if (i == 0) return a;
2042         if (i == num + 1) return b;
2043 
2044         BigInteger curBI = startBI.add(intervalBI.multiply(BigInteger.valueOf(i)));
2045         byte [] padded = curBI.toByteArray();
2046         if (padded[1] == 0)
2047           padded = tail(padded, padded.length - 2);
2048         else
2049           padded = tail(padded, padded.length - 1);
2050         return padded;
2051       }
2052 
2053       @Override
2054       public void remove() {
2055         throw new UnsupportedOperationException();
2056       }
2057 
2058     };
2059 
2060     return new Iterable<byte[]>() {
2061       @Override
2062       public Iterator<byte[]> iterator() {
2063         return iterator;
2064       }
2065     };
2066   }
2067 
2068   /**
2069    * @param bytes array to hash
2070    * @param offset offset to start from
2071    * @param length length to hash
2072    * */
2073   public static int hashCode(byte[] bytes, int offset, int length) {
2074     int hash = 1;
2075     for (int i = offset; i < offset + length; i++)
2076       hash = (31 * hash) + (int) bytes[i];
2077     return hash;
2078   }
2079 
2080   /**
2081    * @param t operands
2082    * @return Array of byte arrays made from passed array of Text
2083    */
2084   public static byte [][] toByteArrays(final String [] t) {
2085     byte [][] result = new byte[t.length][];
2086     for (int i = 0; i < t.length; i++) {
2087       result[i] = Bytes.toBytes(t[i]);
2088     }
2089     return result;
2090   }
2091 
2092   /**
2093    * @param t operands
2094    * @return Array of binary byte arrays made from passed array of binary strings
2095    */
2096   public static byte[][] toBinaryByteArrays(final String[] t) {
2097     byte[][] result = new byte[t.length][];
2098     for (int i = 0; i < t.length; i++) {
2099       result[i] = Bytes.toBytesBinary(t[i]);
2100     }
2101     return result;
2102   }
2103 
2104   /**
2105    * @param column operand
2106    * @return A byte array of a byte array where first and only entry is
2107    * <code>column</code>
2108    */
2109   public static byte [][] toByteArrays(final String column) {
2110     return toByteArrays(toBytes(column));
2111   }
2112 
2113   /**
2114    * @param column operand
2115    * @return A byte array of a byte array where first and only entry is
2116    * <code>column</code>
2117    */
2118   public static byte [][] toByteArrays(final byte [] column) {
2119     byte [][] result = new byte[1][];
2120     result[0] = column;
2121     return result;
2122   }
2123 
2124   /**
2125    * Binary search for keys in indexes.
2126    *
2127    * @param arr array of byte arrays to search for
2128    * @param key the key you want to find
2129    * @param offset the offset in the key you want to find
2130    * @param length the length of the key
2131    * @param comparator a comparator to compare.
2132    * @return zero-based index of the key, if the key is present in the array.
2133    *         Otherwise, a value -(i + 1) such that the key is between arr[i -
2134    *         1] and arr[i] non-inclusively, where i is in [0, i], if we define
2135    *         arr[-1] = -Inf and arr[N] = Inf for an N-element array. The above
2136    *         means that this function can return 2N + 1 different values
2137    *         ranging from -(N + 1) to N - 1.
2138    */
2139   public static int binarySearch(byte [][]arr, byte []key, int offset,
2140       int length, RawComparator<?> comparator) {
2141     int low = 0;
2142     int high = arr.length - 1;
2143 
2144     while (low <= high) {
2145       int mid = low + ((high - low) >> 1);
2146       // we have to compare in this order, because the comparator order
2147       // has special logic when the 'left side' is a special key.
2148       int cmp = comparator.compare(key, offset, length,
2149           arr[mid], 0, arr[mid].length);
2150       // key lives above the midpoint
2151       if (cmp > 0)
2152         low = mid + 1;
2153       // key lives below the midpoint
2154       else if (cmp < 0)
2155         high = mid - 1;
2156       // BAM. how often does this really happen?
2157       else
2158         return mid;
2159     }
2160     return - (low+1);
2161   }
2162 
2163   /**
2164    * Binary search for keys in indexes.
2165    *
2166    * @param arr array of byte arrays to search for
2167    * @param key the key you want to find
2168    * @param comparator a comparator to compare.
2169    * @return zero-based index of the key, if the key is present in the array.
2170    *         Otherwise, a value -(i + 1) such that the key is between arr[i -
2171    *         1] and arr[i] non-inclusively, where i is in [0, i], if we define
2172    *         arr[-1] = -Inf and arr[N] = Inf for an N-element array. The above
2173    *         means that this function can return 2N + 1 different values
2174    *         ranging from -(N + 1) to N - 1.
2175    * @return the index of the block
2176    */
2177   public static int binarySearch(byte[][] arr, Cell key, RawComparator<Cell> comparator) {
2178     int low = 0;
2179     int high = arr.length - 1;
2180     KeyValue.KeyOnlyKeyValue r = new KeyValue.KeyOnlyKeyValue();
2181     while (low <= high) {
2182       int mid = low + ((high - low) >> 1);
2183       // we have to compare in this order, because the comparator order
2184       // has special logic when the 'left side' is a special key.
2185       r.setKey(arr[mid], 0, arr[mid].length);
2186       int cmp = comparator.compare(key, r);
2187       // key lives above the midpoint
2188       if (cmp > 0)
2189         low = mid + 1;
2190       // key lives below the midpoint
2191       else if (cmp < 0)
2192         high = mid - 1;
2193       // BAM. how often does this really happen?
2194       else
2195         return mid;
2196     }
2197     return - (low+1);
2198   }
2199 
2200   /**
2201    * Bytewise binary increment/deincrement of long contained in byte array
2202    * on given amount.
2203    *
2204    * @param value - array of bytes containing long (length &lt;= SIZEOF_LONG)
2205    * @param amount value will be incremented on (deincremented if negative)
2206    * @return array of bytes containing incremented long (length == SIZEOF_LONG)
2207    */
2208   public static byte [] incrementBytes(byte[] value, long amount)
2209   {
2210     byte[] val = value;
2211     if (val.length < SIZEOF_LONG) {
2212       // Hopefully this doesn't happen too often.
2213       byte [] newvalue;
2214       if (val[0] < 0) {
2215         newvalue = new byte[]{-1, -1, -1, -1, -1, -1, -1, -1};
2216       } else {
2217         newvalue = new byte[SIZEOF_LONG];
2218       }
2219       System.arraycopy(val, 0, newvalue, newvalue.length - val.length,
2220         val.length);
2221       val = newvalue;
2222     } else if (val.length > SIZEOF_LONG) {
2223       throw new IllegalArgumentException("Increment Bytes - value too big: " +
2224         val.length);
2225     }
2226     if(amount == 0) return val;
2227     if(val[0] < 0){
2228       return binaryIncrementNeg(val, amount);
2229     }
2230     return binaryIncrementPos(val, amount);
2231   }
2232 
2233   /* increment/deincrement for positive value */
2234   private static byte [] binaryIncrementPos(byte [] value, long amount) {
2235     long amo = amount;
2236     int sign = 1;
2237     if (amount < 0) {
2238       amo = -amount;
2239       sign = -1;
2240     }
2241     for(int i=0;i<value.length;i++) {
2242       int cur = ((int)amo % 256) * sign;
2243       amo = (amo >> 8);
2244       int val = value[value.length-i-1] & 0x0ff;
2245       int total = val + cur;
2246       if(total > 255) {
2247         amo += sign;
2248         total %= 256;
2249       } else if (total < 0) {
2250         amo -= sign;
2251       }
2252       value[value.length-i-1] = (byte)total;
2253       if (amo == 0) return value;
2254     }
2255     return value;
2256   }
2257 
2258   /* increment/deincrement for negative value */
2259   private static byte [] binaryIncrementNeg(byte [] value, long amount) {
2260     long amo = amount;
2261     int sign = 1;
2262     if (amount < 0) {
2263       amo = -amount;
2264       sign = -1;
2265     }
2266     for(int i=0;i<value.length;i++) {
2267       int cur = ((int)amo % 256) * sign;
2268       amo = (amo >> 8);
2269       int val = ((~value[value.length-i-1]) & 0x0ff) + 1;
2270       int total = cur - val;
2271       if(total >= 0) {
2272         amo += sign;
2273       } else if (total < -256) {
2274         amo -= sign;
2275         total %= 256;
2276       }
2277       value[value.length-i-1] = (byte)total;
2278       if (amo == 0) return value;
2279     }
2280     return value;
2281   }
2282 
2283   /**
2284    * Writes a string as a fixed-size field, padded with zeros.
2285    */
2286   public static void writeStringFixedSize(final DataOutput out, String s,
2287       int size) throws IOException {
2288     byte[] b = toBytes(s);
2289     if (b.length > size) {
2290       throw new IOException("Trying to write " + b.length + " bytes (" +
2291           toStringBinary(b) + ") into a field of length " + size);
2292     }
2293 
2294     out.writeBytes(s);
2295     for (int i = 0; i < size - s.length(); ++i)
2296       out.writeByte(0);
2297   }
2298 
2299   /**
2300    * Reads a fixed-size field and interprets it as a string padded with zeros.
2301    */
2302   public static String readStringFixedSize(final DataInput in, int size)
2303       throws IOException {
2304     byte[] b = new byte[size];
2305     in.readFully(b);
2306     int n = b.length;
2307     while (n > 0 && b[n - 1] == 0)
2308       --n;
2309 
2310     return toString(b, 0, n);
2311   }
2312 
2313   /**
2314    * Copy the byte array given in parameter and return an instance
2315    * of a new byte array with the same length and the same content.
2316    * @param bytes the byte array to duplicate
2317    * @return a copy of the given byte array
2318    */
2319   public static byte [] copy(byte [] bytes) {
2320     if (bytes == null) return null;
2321     byte [] result = new byte[bytes.length];
2322     System.arraycopy(bytes, 0, result, 0, bytes.length);
2323     return result;
2324   }
2325 
2326   /**
2327    * Copy the byte array given in parameter and return an instance
2328    * of a new byte array with the same length and the same content.
2329    * @param bytes the byte array to copy from
2330    * @return a copy of the given designated byte array
2331    * @param offset
2332    * @param length
2333    */
2334   public static byte [] copy(byte [] bytes, final int offset, final int length) {
2335     if (bytes == null) return null;
2336     byte [] result = new byte[length];
2337     System.arraycopy(bytes, offset, result, 0, length);
2338     return result;
2339   }
2340 
2341   /**
2342    * Search sorted array "a" for byte "key". I can't remember if I wrote this or copied it from
2343    * somewhere. (mcorgan)
2344    * @param a Array to search. Entries must be sorted and unique.
2345    * @param fromIndex First index inclusive of "a" to include in the search.
2346    * @param toIndex Last index exclusive of "a" to include in the search.
2347    * @param key The byte to search for.
2348    * @return The index of key if found. If not found, return -(index + 1), where negative indicates
2349    *         "not found" and the "index + 1" handles the "-0" case.
2350    */
2351   public static int unsignedBinarySearch(byte[] a, int fromIndex, int toIndex, byte key) {
2352     int unsignedKey = key & 0xff;
2353     int low = fromIndex;
2354     int high = toIndex - 1;
2355 
2356     while (low <= high) {
2357       int mid = low + ((high - low) >> 1);
2358       int midVal = a[mid] & 0xff;
2359 
2360       if (midVal < unsignedKey) {
2361         low = mid + 1;
2362       } else if (midVal > unsignedKey) {
2363         high = mid - 1;
2364       } else {
2365         return mid; // key found
2366       }
2367     }
2368     return -(low + 1); // key not found.
2369   }
2370 
2371   /**
2372    * Treat the byte[] as an unsigned series of bytes, most significant bits first.  Start by adding
2373    * 1 to the rightmost bit/byte and carry over all overflows to the more significant bits/bytes.
2374    *
2375    * @param input The byte[] to increment.
2376    * @return The incremented copy of "in".  May be same length or 1 byte longer.
2377    */
2378   public static byte[] unsignedCopyAndIncrement(final byte[] input) {
2379     byte[] copy = copy(input);
2380     if (copy == null) {
2381       throw new IllegalArgumentException("cannot increment null array");
2382     }
2383     for (int i = copy.length - 1; i >= 0; --i) {
2384       if (copy[i] == -1) {// -1 is all 1-bits, which is the unsigned maximum
2385         copy[i] = 0;
2386       } else {
2387         ++copy[i];
2388         return copy;
2389       }
2390     }
2391     // we maxed out the array
2392     byte[] out = new byte[copy.length + 1];
2393     out[0] = 1;
2394     System.arraycopy(copy, 0, out, 1, copy.length);
2395     return out;
2396   }
2397 
2398   public static boolean equals(List<byte[]> a, List<byte[]> b) {
2399     if (a == null) {
2400       if (b == null) {
2401         return true;
2402       }
2403       return false;
2404     }
2405     if (b == null) {
2406       return false;
2407     }
2408     if (a.size() != b.size()) {
2409       return false;
2410     }
2411     for (int i = 0; i < a.size(); ++i) {
2412       if (!Bytes.equals(a.get(i), b.get(i))) {
2413         return false;
2414       }
2415     }
2416     return true;
2417   }
2418 
2419   public static boolean isSorted(Collection<byte[]> arrays) {
2420     byte[] previous = new byte[0];
2421     for (byte[] array : IterableUtils.nullSafe(arrays)) {
2422       if (Bytes.compareTo(previous, array) > 0) {
2423         return false;
2424       }
2425       previous = array;
2426     }
2427     return true;
2428   }
2429 
2430   public static List<byte[]> getUtf8ByteArrays(List<String> strings) {
2431     List<byte[]> byteArrays = Lists.newArrayListWithCapacity(CollectionUtils.nullSafeSize(strings));
2432     for (String s : IterableUtils.nullSafe(strings)) {
2433       byteArrays.add(Bytes.toBytes(s));
2434     }
2435     return byteArrays;
2436   }
2437 
2438   /**
2439    * Returns the index of the first appearance of the value {@code target} in
2440    * {@code array}.
2441    *
2442    * @param array an array of {@code byte} values, possibly empty
2443    * @param target a primitive {@code byte} value
2444    * @return the least index {@code i} for which {@code array[i] == target}, or
2445    *     {@code -1} if no such index exists.
2446    */
2447   public static int indexOf(byte[] array, byte target) {
2448     for (int i = 0; i < array.length; i++) {
2449       if (array[i] == target) {
2450         return i;
2451       }
2452     }
2453     return -1;
2454   }
2455 
2456   /**
2457    * Returns the start position of the first occurrence of the specified {@code
2458    * target} within {@code array}, or {@code -1} if there is no such occurrence.
2459    *
2460    * <p>More formally, returns the lowest index {@code i} such that {@code
2461    * java.util.Arrays.copyOfRange(array, i, i + target.length)} contains exactly
2462    * the same elements as {@code target}.
2463    *
2464    * @param array the array to search for the sequence {@code target}
2465    * @param target the array to search for as a sub-sequence of {@code array}
2466    */
2467   public static int indexOf(byte[] array, byte[] target) {
2468     checkNotNull(array, "array");
2469     checkNotNull(target, "target");
2470     if (target.length == 0) {
2471       return 0;
2472     }
2473 
2474     outer:
2475     for (int i = 0; i < array.length - target.length + 1; i++) {
2476       for (int j = 0; j < target.length; j++) {
2477         if (array[i + j] != target[j]) {
2478           continue outer;
2479         }
2480       }
2481       return i;
2482     }
2483     return -1;
2484   }
2485 
2486   /**
2487    * @param array an array of {@code byte} values, possibly empty
2488    * @param target a primitive {@code byte} value
2489    * @return {@code true} if {@code target} is present as an element anywhere in {@code array}.
2490    */
2491   public static boolean contains(byte[] array, byte target) {
2492     return indexOf(array, target) > -1;
2493   }
2494 
2495   /**
2496    * @param array an array of {@code byte} values, possibly empty
2497    * @param target an array of {@code byte}
2498    * @return {@code true} if {@code target} is present anywhere in {@code array}
2499    */
2500   public static boolean contains(byte[] array, byte[] target) {
2501     return indexOf(array, target) > -1;
2502   }
2503 
2504   /**
2505    * Fill given array with zeros.
2506    * @param b array which needs to be filled with zeros
2507    */
2508   public static void zero(byte[] b) {
2509     zero(b, 0, b.length);
2510   }
2511 
2512   /**
2513    * Fill given array with zeros at the specified position.
2514    * @param b
2515    * @param offset
2516    * @param length
2517    */
2518   public static void zero(byte[] b, int offset, int length) {
2519     checkPositionIndex(offset, b.length, "offset");
2520     checkArgument(length > 0, "length must be greater than 0");
2521     checkPositionIndex(offset + length, b.length, "offset + length");
2522     Arrays.fill(b, offset, offset + length, (byte) 0);
2523   }
2524 
2525   private static final SecureRandom RNG = new SecureRandom();
2526 
2527   /**
2528    * Fill given array with random bytes.
2529    * @param b array which needs to be filled with random bytes
2530    */
2531   public static void random(byte[] b) {
2532     RNG.nextBytes(b);
2533   }
2534 
2535   /**
2536    * Fill given array with random bytes at the specified position.
2537    * @param b
2538    * @param offset
2539    * @param length
2540    */
2541   public static void random(byte[] b, int offset, int length) {
2542     checkPositionIndex(offset, b.length, "offset");
2543     checkArgument(length > 0, "length must be greater than 0");
2544     checkPositionIndex(offset + length, b.length, "offset + length");
2545     byte[] buf = new byte[length];
2546     RNG.nextBytes(buf);
2547     System.arraycopy(buf, 0, b, offset, length);
2548   }
2549 
2550   /**
2551    * Create a max byte array with the specified max byte count
2552    * @param maxByteCount the length of returned byte array
2553    * @return the created max byte array
2554    */
2555   public static byte[] createMaxByteArray(int maxByteCount) {
2556     byte[] maxByteArray = new byte[maxByteCount];
2557     for (int i = 0; i < maxByteArray.length; i++) {
2558       maxByteArray[i] = (byte) 0xff;
2559     }
2560     return maxByteArray;
2561   }
2562 
2563   /**
2564    * Create a byte array which is multiple given bytes
2565    * @param srcBytes
2566    * @param multiNum
2567    * @return byte array
2568    */
2569   public static byte[] multiple(byte[] srcBytes, int multiNum) {
2570     if (multiNum <= 0) {
2571       return new byte[0];
2572     }
2573     byte[] result = new byte[srcBytes.length * multiNum];
2574     for (int i = 0; i < multiNum; i++) {
2575       System.arraycopy(srcBytes, 0, result, i * srcBytes.length,
2576         srcBytes.length);
2577     }
2578     return result;
2579   }
2580 
2581   private static final char[] HEX_CHARS = {
2582     '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'
2583   };
2584 
2585   /**
2586    * Convert a byte range into a hex string
2587    */
2588   public static String toHex(byte[] b, int offset, int length) {
2589     checkArgument(length <= Integer.MAX_VALUE / 2);
2590     int numChars = length * 2;
2591     char[] ch = new char[numChars];
2592     for (int i = 0; i < numChars; i += 2)
2593     {
2594       byte d = b[offset + i/2];
2595       ch[i] = HEX_CHARS[(d >> 4) & 0x0F];
2596       ch[i+1] = HEX_CHARS[d & 0x0F];
2597     }
2598     return new String(ch);
2599   }
2600 
2601   /**
2602    * Convert a byte array into a hex string
2603    */
2604   public static String toHex(byte[] b) {
2605     return toHex(b, 0, b.length);
2606   }
2607 
2608   private static int hexCharToNibble(char ch) {
2609     if (ch <= '9' && ch >= '0') {
2610       return ch - '0';
2611     } else if (ch >= 'a' && ch <= 'f') {
2612       return ch - 'a' + 10;
2613     } else if (ch >= 'A' && ch <= 'F') {
2614       return ch - 'A' + 10;
2615     }
2616     throw new IllegalArgumentException("Invalid hex char: " + ch);
2617   }
2618 
2619   private static byte hexCharsToByte(char c1, char c2) {
2620     return (byte) ((hexCharToNibble(c1) << 4) | hexCharToNibble(c2));
2621   }
2622 
2623   /**
2624    * Create a byte array from a string of hash digits. The length of the
2625    * string must be a multiple of 2
2626    * @param hex
2627    */
2628   public static byte[] fromHex(String hex) {
2629     checkArgument(hex.length() % 2 == 0, "length must be a multiple of 2");
2630     int len = hex.length();
2631     byte[] b = new byte[len / 2];
2632     for (int i = 0; i < len; i += 2) {
2633         b[i / 2] = hexCharsToByte(hex.charAt(i),hex.charAt(i+1));
2634     }
2635     return b;
2636   }
2637 
2638 }