View Javadoc

1   /**
2    * Copyright 2010 The Apache Software Foundation
3    *
4    * Licensed to the Apache Software Foundation (ASF) under one
5    * or more contributor license agreements.  See the NOTICE file
6    * distributed with this work for additional information
7    * regarding copyright ownership.  The ASF licenses this file
8    * to you under the Apache License, Version 2.0 (the
9    * "License"); you may not use this file except in compliance
10   * with the License.  You may obtain a copy of the License at
11   *
12   *     http://www.apache.org/licenses/LICENSE-2.0
13   *
14   * Unless required by applicable law or agreed to in writing, software
15   * distributed under the License is distributed on an "AS IS" BASIS,
16   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17   * See the License for the specific language governing permissions and
18   * limitations under the License.
19   */
20  package org.apache.hadoop.hbase.util;
21  
22  import java.io.DataInput;
23  import java.io.DataOutput;
24  import java.io.IOException;
25  import java.io.UnsupportedEncodingException;
26  import java.lang.reflect.Field;
27  import java.math.BigDecimal;
28  import java.math.BigInteger;
29  import java.nio.ByteBuffer;
30  import java.nio.ByteOrder;
31  import java.security.AccessController;
32  import java.security.PrivilegedAction;
33  import java.util.Comparator;
34  import java.util.Iterator;
35  
36  import org.apache.commons.logging.Log;
37  import org.apache.commons.logging.LogFactory;
38  import org.apache.hadoop.hbase.HConstants;
39  import org.apache.hadoop.hbase.io.ImmutableBytesWritable;
40  import org.apache.hadoop.io.RawComparator;
41  import org.apache.hadoop.io.WritableComparator;
42  import org.apache.hadoop.io.WritableUtils;
43  
44  import sun.misc.Unsafe;
45  
46  import com.google.common.annotations.VisibleForTesting;
47  
48  /**
49   * Utility class that handles byte arrays, conversions to/from other types,
50   * comparisons, hash code generation, manufacturing keys for HashMaps or
51   * HashSets, etc.
52   */
53  public class Bytes {
54  
55    private static final Log LOG = LogFactory.getLog(Bytes.class);
56  
57    /**
58     * Size of boolean in bytes
59     */
60    public static final int SIZEOF_BOOLEAN = Byte.SIZE / Byte.SIZE;
61  
62    /**
63     * Size of byte in bytes
64     */
65    public static final int SIZEOF_BYTE = SIZEOF_BOOLEAN;
66  
67    /**
68     * Size of char in bytes
69     */
70    public static final int SIZEOF_CHAR = Character.SIZE / Byte.SIZE;
71  
72    /**
73     * Size of double in bytes
74     */
75    public static final int SIZEOF_DOUBLE = Double.SIZE / Byte.SIZE;
76  
77    /**
78     * Size of float in bytes
79     */
80    public static final int SIZEOF_FLOAT = Float.SIZE / Byte.SIZE;
81  
82    /**
83     * Size of int in bytes
84     */
85    public static final int SIZEOF_INT = Integer.SIZE / Byte.SIZE;
86  
87    /**
88     * Size of long in bytes
89     */
90    public static final int SIZEOF_LONG = Long.SIZE / Byte.SIZE;
91  
92    /**
93     * Size of short in bytes
94     */
95    public static final int SIZEOF_SHORT = Short.SIZE / Byte.SIZE;
96  
97  
98    /**
99     * Estimate of size cost to pay beyond payload in jvm for instance of byte [].
100    * Estimate based on study of jhat and jprofiler numbers.
101    */
102   // JHat says BU is 56 bytes.
103   // SizeOf which uses java.lang.instrument says 24 bytes. (3 longs?)
104   public static final int ESTIMATED_HEAP_TAX = 16;
105 
106   /**
107    * Byte array comparator class.
108    */
109   public static class ByteArrayComparator implements RawComparator<byte []> {
110     /**
111      * Constructor
112      */
113     public ByteArrayComparator() {
114       super();
115     }
116     public int compare(byte [] left, byte [] right) {
117       return compareTo(left, right);
118     }
119     public int compare(byte [] b1, int s1, int l1, byte [] b2, int s2, int l2) {
120       return LexicographicalComparerHolder.BEST_COMPARER.
121         compareTo(b1, s1, l1, b2, s2, l2);
122     }
123   }
124 
125   /**
126    * A {@link ByteArrayComparator} that treats the empty array as the largest value.
127    * This is useful for comparing row end keys for regions.
128    */
129   // TODO: unfortunately, HBase uses byte[0] as both start and end keys for region
130   // boundaries. Thus semantically, we should treat empty byte array as the smallest value
131   // while comparing row keys, start keys etc; but as the largest value for comparing
132   // region boundaries for endKeys.
133   public static class RowEndKeyComparator extends ByteArrayComparator {
134     @Override
135     public int compare(byte[] left, byte[] right) {
136       return compare(left, 0, left.length, right, 0, right.length);
137     }
138     @Override
139     public int compare(byte[] b1, int s1, int l1, byte[] b2, int s2, int l2) {
140       if (b1 == b2 && s1 == s2 && l1 == l2) {
141         return 0;
142       }
143       if (l1 == 0) {
144         return l2; //0 or positive
145       }
146       if (l2 == 0) {
147         return -1;
148       }
149       return super.compare(b1, s1, l1, b2, s2, l2);
150     }
151   }
152 
153   /**
154    * Pass this to TreeMaps where byte [] are keys.
155    */
156   public static Comparator<byte []> BYTES_COMPARATOR =
157     new ByteArrayComparator();
158 
159   /**
160    * Use comparing byte arrays, byte-by-byte
161    */
162   public static RawComparator<byte []> BYTES_RAWCOMPARATOR =
163     new ByteArrayComparator();
164 
165   /**
166    * Read byte-array written with a WritableableUtils.vint prefix.
167    * @param in Input to read from.
168    * @return byte array read off <code>in</code>
169    * @throws IOException e
170    */
171   public static byte [] readByteArray(final DataInput in)
172   throws IOException {
173     int len = WritableUtils.readVInt(in);
174     if (len < 0) {
175       throw new NegativeArraySizeException(Integer.toString(len));
176     }
177     byte [] result = new byte[len];
178     in.readFully(result, 0, len);
179     return result;
180   }
181 
182   /**
183    * Read byte-array written with a WritableableUtils.vint prefix.
184    * IOException is converted to a RuntimeException.
185    * @param in Input to read from.
186    * @return byte array read off <code>in</code>
187    */
188   public static byte [] readByteArrayThrowsRuntime(final DataInput in) {
189     try {
190       return readByteArray(in);
191     } catch (Exception e) {
192       throw new RuntimeException(e);
193     }
194   }
195 
196   /**
197    * Write byte-array with a WritableableUtils.vint prefix.
198    * @param out output stream to be written to
199    * @param b array to write
200    * @throws IOException e
201    */
202   public static void writeByteArray(final DataOutput out, final byte [] b)
203   throws IOException {
204     if(b == null) {
205       WritableUtils.writeVInt(out, 0);
206     } else {
207       writeByteArray(out, b, 0, b.length);
208     }
209   }
210 
211   /**
212    * Write byte-array to out with a vint length prefix.
213    * @param out output stream
214    * @param b array
215    * @param offset offset into array
216    * @param length length past offset
217    * @throws IOException e
218    */
219   public static void writeByteArray(final DataOutput out, final byte [] b,
220       final int offset, final int length)
221   throws IOException {
222     WritableUtils.writeVInt(out, length);
223     out.write(b, offset, length);
224   }
225 
226   /**
227    * Write byte-array from src to tgt with a vint length prefix.
228    * @param tgt target array
229    * @param tgtOffset offset into target array
230    * @param src source array
231    * @param srcOffset source offset
232    * @param srcLength source length
233    * @return New offset in src array.
234    */
235   public static int writeByteArray(final byte [] tgt, final int tgtOffset,
236       final byte [] src, final int srcOffset, final int srcLength) {
237     byte [] vint = vintToBytes(srcLength);
238     System.arraycopy(vint, 0, tgt, tgtOffset, vint.length);
239     int offset = tgtOffset + vint.length;
240     System.arraycopy(src, srcOffset, tgt, offset, srcLength);
241     return offset + srcLength;
242   }
243 
244   /**
245    * Put bytes at the specified byte array position.
246    * @param tgtBytes the byte array
247    * @param tgtOffset position in the array
248    * @param srcBytes array to write out
249    * @param srcOffset source offset
250    * @param srcLength source length
251    * @return incremented offset
252    */
253   public static int putBytes(byte[] tgtBytes, int tgtOffset, byte[] srcBytes,
254       int srcOffset, int srcLength) {
255     System.arraycopy(srcBytes, srcOffset, tgtBytes, tgtOffset, srcLength);
256     return tgtOffset + srcLength;
257   }
258 
259   /**
260    * Write a single byte out to the specified byte array position.
261    * @param bytes the byte array
262    * @param offset position in the array
263    * @param b byte to write out
264    * @return incremented offset
265    */
266   public static int putByte(byte[] bytes, int offset, byte b) {
267     bytes[offset] = b;
268     return offset + 1;
269   }
270 
271   /**
272    * Returns a new byte array, copied from the passed ByteBuffer.
273    * @param bb A ByteBuffer
274    * @return the byte array
275    */
276   public static byte[] toBytes(ByteBuffer bb) {
277     int length = bb.limit();
278     byte [] result = new byte[length];
279     System.arraycopy(bb.array(), bb.arrayOffset(), result, 0, length);
280     return result;
281   }
282 
283   /**
284    * @param b Presumed UTF-8 encoded byte array.
285    * @return String made from <code>b</code>
286    */
287   public static String toString(final byte [] b) {
288     if (b == null) {
289       return null;
290     }
291     return toString(b, 0, b.length);
292   }
293 
294   /**
295    * Joins two byte arrays together using a separator.
296    * @param b1 The first byte array.
297    * @param sep The separator to use.
298    * @param b2 The second byte array.
299    */
300   public static String toString(final byte [] b1,
301                                 String sep,
302                                 final byte [] b2) {
303     return toString(b1, 0, b1.length) + sep + toString(b2, 0, b2.length);
304   }
305 
306   /**
307    * This method will convert utf8 encoded bytes into a string. If
308    * an UnsupportedEncodingException occurs, this method will eat it
309    * and return null instead.
310    *
311    * @param b Presumed UTF-8 encoded byte array.
312    * @param off offset into array
313    * @param len length of utf-8 sequence
314    * @return String made from <code>b</code> or null
315    */
316   public static String toString(final byte [] b, int off, int len) {
317     if (b == null) {
318       return null;
319     }
320     if (len == 0) {
321       return "";
322     }
323     try {
324       return new String(b, off, len, HConstants.UTF8_ENCODING);
325     } catch (UnsupportedEncodingException e) {
326       LOG.error("UTF-8 not supported?", e);
327       return null;
328     }
329   }
330 
331   /**
332    * Write a printable representation of a byte array.
333    *
334    * @param b byte array
335    * @return string
336    * @see #toStringBinary(byte[], int, int)
337    */
338   public static String toStringBinary(final byte [] b) {
339     if (b == null)
340       return "null";
341     return toStringBinary(b, 0, b.length);
342   }
343 
344   /**
345    * Converts the given byte buffer, from its array offset to its limit, to
346    * a string. The position and the mark are ignored.
347    *
348    * @param buf a byte buffer
349    * @return a string representation of the buffer's binary contents
350    */
351   public static String toStringBinary(ByteBuffer buf) {
352     if (buf == null)
353       return "null";
354     return toStringBinary(buf.array(), buf.arrayOffset(), buf.limit());
355   }
356 
357   /**
358    * Write a printable representation of a byte array. Non-printable
359    * characters are hex escaped in the format \\x%02X, eg:
360    * \x00 \x05 etc
361    *
362    * @param b array to write out
363    * @param off offset to start at
364    * @param len length to write
365    * @return string output
366    */
367   public static String toStringBinary(final byte [] b, int off, int len) {
368     StringBuilder result = new StringBuilder();
369     for (int i = off; i < off + len ; ++i ) {
370       int ch = b[i] & 0xFF;
371       if ( (ch >= '0' && ch <= '9')
372           || (ch >= 'A' && ch <= 'Z')
373           || (ch >= 'a' && ch <= 'z')
374           || " `~!@#$%^&*()-_=+[]{}|;:'\",.<>/?".indexOf(ch) >= 0 ) {
375           result.append((char)ch);
376       } else {
377         result.append(String.format("\\x%02X", ch));
378       }
379     }
380     return result.toString();
381   }
382 
383   private static boolean isHexDigit(char c) {
384     return
385         (c >= 'A' && c <= 'F') ||
386         (c >= '0' && c <= '9');
387   }
388 
389   /**
390    * Takes a ASCII digit in the range A-F0-9 and returns
391    * the corresponding integer/ordinal value.
392    * @param ch  The hex digit.
393    * @return The converted hex value as a byte.
394    */
395   public static byte toBinaryFromHex(byte ch) {
396     if ( ch >= 'A' && ch <= 'F' )
397       return (byte) ((byte)10 + (byte) (ch - 'A'));
398     // else
399     return (byte) (ch - '0');
400   }
401 
402   public static byte [] toBytesBinary(String in) {
403     // this may be bigger than we need, but let's be safe.
404     byte [] b = new byte[in.length()];
405     int size = 0;
406     for (int i = 0; i < in.length(); ++i) {
407       char ch = in.charAt(i);
408       if (ch == '\\' && in.length() > i+1 && in.charAt(i+1) == 'x') {
409         // ok, take next 2 hex digits.
410         char hd1 = in.charAt(i+2);
411         char hd2 = in.charAt(i+3);
412 
413         // they need to be A-F0-9:
414         if (!isHexDigit(hd1) ||
415             !isHexDigit(hd2)) {
416           // bogus escape code, ignore:
417           continue;
418         }
419         // turn hex ASCII digit -> number
420         byte d = (byte) ((toBinaryFromHex((byte)hd1) << 4) + toBinaryFromHex((byte)hd2));
421 
422         b[size++] = d;
423         i += 3; // skip 3
424       } else {
425         b[size++] = (byte) ch;
426       }
427     }
428     // resize:
429     byte [] b2 = new byte[size];
430     System.arraycopy(b, 0, b2, 0, size);
431     return b2;
432   }
433 
434   /**
435    * Converts a string to a UTF-8 byte array.
436    * @param s string
437    * @return the byte array
438    */
439   public static byte[] toBytes(String s) {
440     try {
441       return s.getBytes(HConstants.UTF8_ENCODING);
442     } catch (UnsupportedEncodingException e) {
443       LOG.error("UTF-8 not supported?", e);
444       return null;
445     }
446   }
447 
448   /**
449    * Convert a boolean to a byte array. True becomes -1
450    * and false becomes 0.
451    *
452    * @param b value
453    * @return <code>b</code> encoded in a byte array.
454    */
455   public static byte [] toBytes(final boolean b) {
456     return new byte[] { b ? (byte) -1 : (byte) 0 };
457   }
458 
459   /**
460    * Reverses {@link #toBytes(boolean)}
461    * @param b array
462    * @return True or false.
463    */
464   public static boolean toBoolean(final byte [] b) {
465     if (b.length != 1) {
466       throw new IllegalArgumentException("Array has wrong size: " + b.length);
467     }
468     return b[0] != (byte) 0;
469   }
470 
471   /**
472    * Convert a long value to a byte array using big-endian.
473    *
474    * @param val value to convert
475    * @return the byte array
476    */
477   public static byte[] toBytes(long val) {
478     byte [] b = new byte[8];
479     for (int i = 7; i > 0; i--) {
480       b[i] = (byte) val;
481       val >>>= 8;
482     }
483     b[0] = (byte) val;
484     return b;
485   }
486 
487   /**
488    * Converts a byte array to a long value. Reverses
489    * {@link #toBytes(long)}
490    * @param bytes array
491    * @return the long value
492    */
493   public static long toLong(byte[] bytes) {
494     return toLong(bytes, 0, SIZEOF_LONG);
495   }
496 
497   /**
498    * Converts a byte array to a long value. Assumes there will be
499    * {@link #SIZEOF_LONG} bytes available.
500    *
501    * @param bytes bytes
502    * @param offset offset
503    * @return the long value
504    */
505   public static long toLong(byte[] bytes, int offset) {
506     return toLong(bytes, offset, SIZEOF_LONG);
507   }
508 
509   /**
510    * Converts a byte array to a long value.
511    *
512    * @param bytes array of bytes
513    * @param offset offset into array
514    * @param length length of data (must be {@link #SIZEOF_LONG})
515    * @return the long value
516    * @throws IllegalArgumentException if length is not {@link #SIZEOF_LONG} or
517    * if there's not enough room in the array at the offset indicated.
518    */
519   public static long toLong(byte[] bytes, int offset, final int length) {
520     if (length != SIZEOF_LONG || offset + length > bytes.length) {
521       throw explainWrongLengthOrOffset(bytes, offset, length, SIZEOF_LONG);
522     }
523     long l = 0;
524     for(int i = offset; i < offset + length; i++) {
525       l <<= 8;
526       l ^= bytes[i] & 0xFF;
527     }
528     return l;
529   }
530 
531   private static IllegalArgumentException
532     explainWrongLengthOrOffset(final byte[] bytes,
533                                final int offset,
534                                final int length,
535                                final int expectedLength) {
536     String reason;
537     if (length != expectedLength) {
538       reason = "Wrong length: " + length + ", expected " + expectedLength;
539     } else {
540      reason = "offset (" + offset + ") + length (" + length + ") exceed the"
541         + " capacity of the array: " + bytes.length;
542     }
543     return new IllegalArgumentException(reason);
544   }
545 
546   /**
547    * Put a long value out to the specified byte array position.
548    * @param bytes the byte array
549    * @param offset position in the array
550    * @param val long to write out
551    * @return incremented offset
552    * @throws IllegalArgumentException if the byte array given doesn't have
553    * enough room at the offset specified.
554    */
555   public static int putLong(byte[] bytes, int offset, long val) {
556     if (bytes.length - offset < SIZEOF_LONG) {
557       throw new IllegalArgumentException("Not enough room to put a long at"
558           + " offset " + offset + " in a " + bytes.length + " byte array");
559     }
560     for(int i = offset + 7; i > offset; i--) {
561       bytes[i] = (byte) val;
562       val >>>= 8;
563     }
564     bytes[offset] = (byte) val;
565     return offset + SIZEOF_LONG;
566   }
567 
568   /**
569    * Presumes float encoded as IEEE 754 floating-point "single format"
570    * @param bytes byte array
571    * @return Float made from passed byte array.
572    */
573   public static float toFloat(byte [] bytes) {
574     return toFloat(bytes, 0);
575   }
576 
577   /**
578    * Presumes float encoded as IEEE 754 floating-point "single format"
579    * @param bytes array to convert
580    * @param offset offset into array
581    * @return Float made from passed byte array.
582    */
583   public static float toFloat(byte [] bytes, int offset) {
584     return Float.intBitsToFloat(toInt(bytes, offset, SIZEOF_INT));
585   }
586 
587   /**
588    * @param bytes byte array
589    * @param offset offset to write to
590    * @param f float value
591    * @return New offset in <code>bytes</code>
592    */
593   public static int putFloat(byte [] bytes, int offset, float f) {
594     return putInt(bytes, offset, Float.floatToRawIntBits(f));
595   }
596 
597   /**
598    * @param f float value
599    * @return the float represented as byte []
600    */
601   public static byte [] toBytes(final float f) {
602     // Encode it as int
603     return Bytes.toBytes(Float.floatToRawIntBits(f));
604   }
605 
606   /**
607    * @param bytes byte array
608    * @return Return double made from passed bytes.
609    */
610   public static double toDouble(final byte [] bytes) {
611     return toDouble(bytes, 0);
612   }
613 
614   /**
615    * @param bytes byte array
616    * @param offset offset where double is
617    * @return Return double made from passed bytes.
618    */
619   public static double toDouble(final byte [] bytes, final int offset) {
620     return Double.longBitsToDouble(toLong(bytes, offset, SIZEOF_LONG));
621   }
622 
623   /**
624    * @param bytes byte array
625    * @param offset offset to write to
626    * @param d value
627    * @return New offset into array <code>bytes</code>
628    */
629   public static int putDouble(byte [] bytes, int offset, double d) {
630     return putLong(bytes, offset, Double.doubleToLongBits(d));
631   }
632 
633   /**
634    * Serialize a double as the IEEE 754 double format output. The resultant
635    * array will be 8 bytes long.
636    *
637    * @param d value
638    * @return the double represented as byte []
639    */
640   public static byte [] toBytes(final double d) {
641     // Encode it as a long
642     return Bytes.toBytes(Double.doubleToRawLongBits(d));
643   }
644 
645   /**
646    * Convert an int value to a byte array
647    * @param val value
648    * @return the byte array
649    */
650   public static byte[] toBytes(int val) {
651     byte [] b = new byte[4];
652     for(int i = 3; i > 0; i--) {
653       b[i] = (byte) val;
654       val >>>= 8;
655     }
656     b[0] = (byte) val;
657     return b;
658   }
659 
660   /**
661    * Converts a byte array to an int value
662    * @param bytes byte array
663    * @return the int value
664    */
665   public static int toInt(byte[] bytes) {
666     return toInt(bytes, 0, SIZEOF_INT);
667   }
668 
669   /**
670    * Converts a byte array to an int value
671    * @param bytes byte array
672    * @param offset offset into array
673    * @return the int value
674    */
675   public static int toInt(byte[] bytes, int offset) {
676     return toInt(bytes, offset, SIZEOF_INT);
677   }
678 
679   /**
680    * Converts a byte array to an int value
681    * @param bytes byte array
682    * @param offset offset into array
683    * @param length length of int (has to be {@link #SIZEOF_INT})
684    * @return the int value
685    * @throws IllegalArgumentException if length is not {@link #SIZEOF_INT} or
686    * if there's not enough room in the array at the offset indicated.
687    */
688   public static int toInt(byte[] bytes, int offset, final int length) {
689     if (length != SIZEOF_INT || offset + length > bytes.length) {
690       throw explainWrongLengthOrOffset(bytes, offset, length, SIZEOF_INT);
691     }
692     int n = 0;
693     for(int i = offset; i < (offset + length); i++) {
694       n <<= 8;
695       n ^= bytes[i] & 0xFF;
696     }
697     return n;
698   }
699 
700   /**
701    * Put an int value out to the specified byte array position.
702    * @param bytes the byte array
703    * @param offset position in the array
704    * @param val int to write out
705    * @return incremented offset
706    * @throws IllegalArgumentException if the byte array given doesn't have
707    * enough room at the offset specified.
708    */
709   public static int putInt(byte[] bytes, int offset, int val) {
710     if (bytes.length - offset < SIZEOF_INT) {
711       throw new IllegalArgumentException("Not enough room to put an int at"
712           + " offset " + offset + " in a " + bytes.length + " byte array");
713     }
714     for(int i= offset + 3; i > offset; i--) {
715       bytes[i] = (byte) val;
716       val >>>= 8;
717     }
718     bytes[offset] = (byte) val;
719     return offset + SIZEOF_INT;
720   }
721 
722   /**
723    * Convert a short value to a byte array of {@link #SIZEOF_SHORT} bytes long.
724    * @param val value
725    * @return the byte array
726    */
727   public static byte[] toBytes(short val) {
728     byte[] b = new byte[SIZEOF_SHORT];
729     b[1] = (byte) val;
730     val >>= 8;
731     b[0] = (byte) val;
732     return b;
733   }
734 
735   /**
736    * Converts a byte array to a short value
737    * @param bytes byte array
738    * @return the short value
739    */
740   public static short toShort(byte[] bytes) {
741     return toShort(bytes, 0, SIZEOF_SHORT);
742   }
743 
744   /**
745    * Converts a byte array to a short value
746    * @param bytes byte array
747    * @param offset offset into array
748    * @return the short value
749    */
750   public static short toShort(byte[] bytes, int offset) {
751     return toShort(bytes, offset, SIZEOF_SHORT);
752   }
753 
754   /**
755    * Converts a byte array to a short value
756    * @param bytes byte array
757    * @param offset offset into array
758    * @param length length, has to be {@link #SIZEOF_SHORT}
759    * @return the short value
760    * @throws IllegalArgumentException if length is not {@link #SIZEOF_SHORT}
761    * or if there's not enough room in the array at the offset indicated.
762    */
763   public static short toShort(byte[] bytes, int offset, final int length) {
764     if (length != SIZEOF_SHORT || offset + length > bytes.length) {
765       throw explainWrongLengthOrOffset(bytes, offset, length, SIZEOF_SHORT);
766     }
767     short n = 0;
768     n ^= bytes[offset] & 0xFF;
769     n <<= 8;
770     n ^= bytes[offset+1] & 0xFF;
771     return n;
772   }
773 
774   /**
775    * This method will get a sequence of bytes from pos -> limit,
776    * but will restore pos after.
777    * @param buf
778    * @return byte array
779    */
780   public static byte[] getBytes(ByteBuffer buf) {
781     int savedPos = buf.position();
782     byte [] newBytes = new byte[buf.remaining()];
783     buf.get(newBytes);
784     buf.position(savedPos);
785     return newBytes;
786   }
787 
788   /**
789    * Put a short value out to the specified byte array position.
790    * @param bytes the byte array
791    * @param offset position in the array
792    * @param val short to write out
793    * @return incremented offset
794    * @throws IllegalArgumentException if the byte array given doesn't have
795    * enough room at the offset specified.
796    */
797   public static int putShort(byte[] bytes, int offset, short val) {
798     if (bytes.length - offset < SIZEOF_SHORT) {
799       throw new IllegalArgumentException("Not enough room to put a short at"
800           + " offset " + offset + " in a " + bytes.length + " byte array");
801     }
802     bytes[offset+1] = (byte) val;
803     val >>= 8;
804     bytes[offset] = (byte) val;
805     return offset + SIZEOF_SHORT;
806   }
807 
808   /**
809    * Convert a BigDecimal value to a byte array
810    *
811    * @param val
812    * @return the byte array
813    */
814   public static byte[] toBytes(BigDecimal val) {
815     byte[] valueBytes = val.unscaledValue().toByteArray();
816     byte[] result = new byte[valueBytes.length + SIZEOF_INT];
817     int offset = putInt(result, 0, val.scale());
818     putBytes(result, offset, valueBytes, 0, valueBytes.length);
819     return result;
820   }
821 
822 
823   /**
824    * Converts a byte array to a BigDecimal
825    *
826    * @param bytes
827    * @return the char value
828    */
829   public static BigDecimal toBigDecimal(byte[] bytes) {
830     return toBigDecimal(bytes, 0, bytes.length);
831   }
832 
833   /**
834    * Converts a byte array to a BigDecimal value
835    *
836    * @param bytes
837    * @param offset
838    * @param length
839    * @return the char value
840    */
841   public static BigDecimal toBigDecimal(byte[] bytes, int offset, final int length) {
842     if (bytes == null || length < SIZEOF_INT + 1 ||
843       (offset + length > bytes.length)) {
844       return null;
845     }
846 
847     int scale = toInt(bytes, offset);
848     byte[] tcBytes = new byte[length - SIZEOF_INT];
849     System.arraycopy(bytes, offset + SIZEOF_INT, tcBytes, 0, length - SIZEOF_INT);
850     return new BigDecimal(new BigInteger(tcBytes), scale);
851   }
852 
853   /**
854    * Put a BigDecimal value out to the specified byte array position.
855    *
856    * @param bytes  the byte array
857    * @param offset position in the array
858    * @param val    BigDecimal to write out
859    * @return incremented offset
860    */
861   public static int putBigDecimal(byte[] bytes, int offset, BigDecimal val) {
862     if (bytes == null) {
863       return offset;
864     }
865 
866     byte[] valueBytes = val.unscaledValue().toByteArray();
867     byte[] result = new byte[valueBytes.length + SIZEOF_INT];
868     offset = putInt(result, offset, val.scale());
869     return putBytes(result, offset, valueBytes, 0, valueBytes.length);
870   }
871 
872   /**
873    * @param vint Integer to make a vint of.
874    * @return Vint as bytes array.
875    */
876   public static byte [] vintToBytes(final long vint) {
877     long i = vint;
878     int size = WritableUtils.getVIntSize(i);
879     byte [] result = new byte[size];
880     int offset = 0;
881     if (i >= -112 && i <= 127) {
882       result[offset] = (byte) i;
883       return result;
884     }
885 
886     int len = -112;
887     if (i < 0) {
888       i ^= -1L; // take one's complement'
889       len = -120;
890     }
891 
892     long tmp = i;
893     while (tmp != 0) {
894       tmp = tmp >> 8;
895       len--;
896     }
897 
898     result[offset++] = (byte) len;
899 
900     len = (len < -120) ? -(len + 120) : -(len + 112);
901 
902     for (int idx = len; idx != 0; idx--) {
903       int shiftbits = (idx - 1) * 8;
904       long mask = 0xFFL << shiftbits;
905       result[offset++] = (byte)((i & mask) >> shiftbits);
906     }
907     return result;
908   }
909 
910   /**
911    * @param buffer buffer to convert
912    * @return vint bytes as an integer.
913    */
914   public static long bytesToVint(final byte [] buffer) {
915     int offset = 0;
916     byte firstByte = buffer[offset++];
917     int len = WritableUtils.decodeVIntSize(firstByte);
918     if (len == 1) {
919       return firstByte;
920     }
921     long i = 0;
922     for (int idx = 0; idx < len-1; idx++) {
923       byte b = buffer[offset++];
924       i = i << 8;
925       i = i | (b & 0xFF);
926     }
927     return (WritableUtils.isNegativeVInt(firstByte) ? ~i : i);
928   }
929 
930   /**
931    * Reads a zero-compressed encoded long from input stream and returns it.
932    * @param buffer Binary array
933    * @param offset Offset into array at which vint begins.
934    * @throws java.io.IOException e
935    * @return deserialized long from stream.
936    */
937   public static long readVLong(final byte [] buffer, final int offset)
938   throws IOException {
939     byte firstByte = buffer[offset];
940     int len = WritableUtils.decodeVIntSize(firstByte);
941     if (len == 1) {
942       return firstByte;
943     }
944     long i = 0;
945     for (int idx = 0; idx < len-1; idx++) {
946       byte b = buffer[offset + 1 + idx];
947       i = i << 8;
948       i = i | (b & 0xFF);
949     }
950     return (WritableUtils.isNegativeVInt(firstByte) ? ~i : i);
951   }
952 
953   /**
954    * @param left left operand
955    * @param right right operand
956    * @return 0 if equal, < 0 if left is less than right, etc.
957    */
958   public static int compareTo(final byte [] left, final byte [] right) {
959     return LexicographicalComparerHolder.BEST_COMPARER.
960       compareTo(left, 0, left.length, right, 0, right.length);
961   }
962 
963   /**
964    * Lexicographically compare two arrays.
965    *
966    * @param buffer1 left operand
967    * @param buffer2 right operand
968    * @param offset1 Where to start comparing in the left buffer
969    * @param offset2 Where to start comparing in the right buffer
970    * @param length1 How much to compare from the left buffer
971    * @param length2 How much to compare from the right buffer
972    * @return 0 if equal, < 0 if left is less than right, etc.
973    */
974   public static int compareTo(byte[] buffer1, int offset1, int length1,
975       byte[] buffer2, int offset2, int length2) {
976     return LexicographicalComparerHolder.BEST_COMPARER.
977       compareTo(buffer1, offset1, length1, buffer2, offset2, length2);
978   }
979 
980   interface Comparer<T> {
981     abstract public int compareTo(T buffer1, int offset1, int length1,
982         T buffer2, int offset2, int length2);
983   }
984 
985   @VisibleForTesting
986   static Comparer<byte[]> lexicographicalComparerJavaImpl() {
987     return LexicographicalComparerHolder.PureJavaComparer.INSTANCE;
988   }
989 
990   /**
991    * Provides a lexicographical comparer implementation; either a Java
992    * implementation or a faster implementation based on {@link Unsafe}.
993    *
994    * <p>Uses reflection to gracefully fall back to the Java implementation if
995    * {@code Unsafe} isn't available.
996    */
997   @VisibleForTesting
998   static class LexicographicalComparerHolder {
999     static final String UNSAFE_COMPARER_NAME =
1000         LexicographicalComparerHolder.class.getName() + "$UnsafeComparer";
1001 
1002     static final Comparer<byte[]> BEST_COMPARER = getBestComparer();
1003     /**
1004      * Returns the Unsafe-using Comparer, or falls back to the pure-Java
1005      * implementation if unable to do so.
1006      */
1007     static Comparer<byte[]> getBestComparer() {
1008       try {
1009         Class<?> theClass = Class.forName(UNSAFE_COMPARER_NAME);
1010 
1011         // yes, UnsafeComparer does implement Comparer<byte[]>
1012         @SuppressWarnings("unchecked")
1013         Comparer<byte[]> comparer =
1014           (Comparer<byte[]>) theClass.getEnumConstants()[0];
1015         return comparer;
1016       } catch (Throwable t) { // ensure we really catch *everything*
1017         return lexicographicalComparerJavaImpl();
1018       }
1019     }
1020 
1021     enum PureJavaComparer implements Comparer<byte[]> {
1022       INSTANCE;
1023 
1024       @Override
1025       public int compareTo(byte[] buffer1, int offset1, int length1,
1026           byte[] buffer2, int offset2, int length2) {
1027         // Short circuit equal case
1028         if (buffer1 == buffer2 &&
1029             offset1 == offset2 &&
1030             length1 == length2) {
1031           return 0;
1032         }
1033         // Bring WritableComparator code local
1034         int end1 = offset1 + length1;
1035         int end2 = offset2 + length2;
1036         for (int i = offset1, j = offset2; i < end1 && j < end2; i++, j++) {
1037           int a = (buffer1[i] & 0xff);
1038           int b = (buffer2[j] & 0xff);
1039           if (a != b) {
1040             return a - b;
1041           }
1042         }
1043         return length1 - length2;
1044       }
1045     }
1046 
1047     @VisibleForTesting
1048     enum UnsafeComparer implements Comparer<byte[]> {
1049       INSTANCE;
1050 
1051       static final Unsafe theUnsafe;
1052 
1053       /** The offset to the first element in a byte array. */
1054       static final int BYTE_ARRAY_BASE_OFFSET;
1055 
1056       static {
1057         theUnsafe = (Unsafe) AccessController.doPrivileged(
1058             new PrivilegedAction<Object>() {
1059               @Override
1060               public Object run() {
1061                 try {
1062                   Field f = Unsafe.class.getDeclaredField("theUnsafe");
1063                   f.setAccessible(true);
1064                   return f.get(null);
1065                 } catch (NoSuchFieldException e) {
1066                   // It doesn't matter what we throw;
1067                   // it's swallowed in getBestComparer().
1068                   throw new Error();
1069                 } catch (IllegalAccessException e) {
1070                   throw new Error();
1071                 }
1072               }
1073             });
1074 
1075         BYTE_ARRAY_BASE_OFFSET = theUnsafe.arrayBaseOffset(byte[].class);
1076 
1077         // sanity check - this should never fail
1078         if (theUnsafe.arrayIndexScale(byte[].class) != 1) {
1079           throw new AssertionError();
1080         }
1081       }
1082 
1083       static final boolean littleEndian =
1084         ByteOrder.nativeOrder().equals(ByteOrder.LITTLE_ENDIAN);
1085 
1086       /**
1087        * Returns true if x1 is less than x2, when both values are treated as
1088        * unsigned.
1089        */
1090       static boolean lessThanUnsigned(long x1, long x2) {
1091         return (x1 + Long.MIN_VALUE) < (x2 + Long.MIN_VALUE);
1092       }
1093 
1094       /**
1095        * Lexicographically compare two arrays.
1096        *
1097        * @param buffer1 left operand
1098        * @param buffer2 right operand
1099        * @param offset1 Where to start comparing in the left buffer
1100        * @param offset2 Where to start comparing in the right buffer
1101        * @param length1 How much to compare from the left buffer
1102        * @param length2 How much to compare from the right buffer
1103        * @return 0 if equal, < 0 if left is less than right, etc.
1104        */
1105       @Override
1106       public int compareTo(byte[] buffer1, int offset1, int length1,
1107           byte[] buffer2, int offset2, int length2) {
1108         // Short circuit equal case
1109         if (buffer1 == buffer2 &&
1110             offset1 == offset2 &&
1111             length1 == length2) {
1112           return 0;
1113         }
1114         int minLength = Math.min(length1, length2);
1115         int minWords = minLength / SIZEOF_LONG;
1116         int offset1Adj = offset1 + BYTE_ARRAY_BASE_OFFSET;
1117         int offset2Adj = offset2 + BYTE_ARRAY_BASE_OFFSET;
1118 
1119         /*
1120          * Compare 8 bytes at a time. Benchmarking shows comparing 8 bytes at a
1121          * time is no slower than comparing 4 bytes at a time even on 32-bit.
1122          * On the other hand, it is substantially faster on 64-bit.
1123          */
1124         for (int i = 0; i < minWords * SIZEOF_LONG; i += SIZEOF_LONG) {
1125           long lw = theUnsafe.getLong(buffer1, offset1Adj + (long) i);
1126           long rw = theUnsafe.getLong(buffer2, offset2Adj + (long) i);
1127           long diff = lw ^ rw;
1128 
1129           if (diff != 0) {
1130             if (!littleEndian) {
1131               return lessThanUnsigned(lw, rw) ? -1 : 1;
1132             }
1133 
1134             // Use binary search
1135             int n = 0;
1136             int y;
1137             int x = (int) diff;
1138             if (x == 0) {
1139               x = (int) (diff >>> 32);
1140               n = 32;
1141             }
1142 
1143             y = x << 16;
1144             if (y == 0) {
1145               n += 16;
1146             } else {
1147               x = y;
1148             }
1149 
1150             y = x << 8;
1151             if (y == 0) {
1152               n += 8;
1153             }
1154             return (int) (((lw >>> n) & 0xFFL) - ((rw >>> n) & 0xFFL));
1155           }
1156         }
1157 
1158         // The epilogue to cover the last (minLength % 8) elements.
1159         for (int i = minWords * SIZEOF_LONG; i < minLength; i++) {
1160           int a = (buffer1[offset1 + i] & 0xff);
1161           int b = (buffer2[offset2 + i] & 0xff);
1162           if (a != b) {
1163             return a - b;
1164           }
1165         }
1166         return length1 - length2;
1167       }
1168     }
1169   }
1170 
1171   /**
1172    * @param left left operand
1173    * @param right right operand
1174    * @return True if equal
1175    */
1176   public static boolean equals(final byte [] left, final byte [] right) {
1177     // Could use Arrays.equals?
1178     //noinspection SimplifiableConditionalExpression
1179     if (left == right) return true;
1180     if (left == null || right == null) return false;
1181     if (left.length != right.length) return false;
1182     if (left.length == 0) return true;
1183 
1184     // Since we're often comparing adjacent sorted data,
1185     // it's usual to have equal arrays except for the very last byte
1186     // so check that first
1187     if (left[left.length - 1] != right[right.length - 1]) return false;
1188 
1189     return compareTo(left, right) == 0;
1190   }
1191 
1192   public static boolean equals(final byte[] left, int leftOffset, int leftLen,
1193                                final byte[] right, int rightOffset, int rightLen) {
1194     // short circuit case
1195     if (left == right &&
1196         leftOffset == rightOffset &&
1197         leftLen == rightLen) {
1198       return true;
1199     }
1200     // different lengths fast check
1201     if (leftLen != rightLen) {
1202       return false;
1203     }
1204     if (leftLen == 0) {
1205       return true;
1206     }
1207 
1208     // Since we're often comparing adjacent sorted data,
1209     // it's usual to have equal arrays except for the very last byte
1210     // so check that first
1211     if (left[leftOffset + leftLen - 1] != right[rightOffset + rightLen - 1]) return false;
1212 
1213     return LexicographicalComparerHolder.BEST_COMPARER.
1214       compareTo(left, leftOffset, leftLen, right, rightOffset, rightLen) == 0;
1215   }
1216 
1217 
1218   /**
1219    * Return true if the byte array on the right is a prefix of the byte
1220    * array on the left.
1221    */
1222   public static boolean startsWith(byte[] bytes, byte[] prefix) {
1223     return bytes != null && prefix != null &&
1224       bytes.length >= prefix.length &&
1225       LexicographicalComparerHolder.BEST_COMPARER.
1226         compareTo(bytes, 0, prefix.length, prefix, 0, prefix.length) == 0;
1227   }
1228 
1229   /**
1230    * @param b bytes to hash
1231    * @return Runs {@link WritableComparator#hashBytes(byte[], int)} on the
1232    * passed in array.  This method is what {@link org.apache.hadoop.io.Text} and
1233    * {@link ImmutableBytesWritable} use calculating hash code.
1234    */
1235   public static int hashCode(final byte [] b) {
1236     return hashCode(b, b.length);
1237   }
1238 
1239   /**
1240    * @param b value
1241    * @param length length of the value
1242    * @return Runs {@link WritableComparator#hashBytes(byte[], int)} on the
1243    * passed in array.  This method is what {@link org.apache.hadoop.io.Text} and
1244    * {@link ImmutableBytesWritable} use calculating hash code.
1245    */
1246   public static int hashCode(final byte [] b, final int length) {
1247     return WritableComparator.hashBytes(b, length);
1248   }
1249 
1250   /**
1251    * @param b bytes to hash
1252    * @return A hash of <code>b</code> as an Integer that can be used as key in
1253    * Maps.
1254    */
1255   public static Integer mapKey(final byte [] b) {
1256     return hashCode(b);
1257   }
1258 
1259   /**
1260    * @param b bytes to hash
1261    * @param length length to hash
1262    * @return A hash of <code>b</code> as an Integer that can be used as key in
1263    * Maps.
1264    */
1265   public static Integer mapKey(final byte [] b, final int length) {
1266     return hashCode(b, length);
1267   }
1268 
1269   /**
1270    * @param a lower half
1271    * @param b upper half
1272    * @return New array that has a in lower half and b in upper half.
1273    */
1274   public static byte [] add(final byte [] a, final byte [] b) {
1275     return add(a, b, HConstants.EMPTY_BYTE_ARRAY);
1276   }
1277 
1278   /**
1279    * @param a first third
1280    * @param b second third
1281    * @param c third third
1282    * @return New array made from a, b and c
1283    */
1284   public static byte [] add(final byte [] a, final byte [] b, final byte [] c) {
1285     byte [] result = new byte[a.length + b.length + c.length];
1286     System.arraycopy(a, 0, result, 0, a.length);
1287     System.arraycopy(b, 0, result, a.length, b.length);
1288     System.arraycopy(c, 0, result, a.length + b.length, c.length);
1289     return result;
1290   }
1291 
1292   /**
1293    * @param a array
1294    * @param length amount of bytes to grab
1295    * @return First <code>length</code> bytes from <code>a</code>
1296    */
1297   public static byte [] head(final byte [] a, final int length) {
1298     if (a.length < length) {
1299       return null;
1300     }
1301     byte [] result = new byte[length];
1302     System.arraycopy(a, 0, result, 0, length);
1303     return result;
1304   }
1305 
1306   /**
1307    * @param a array
1308    * @param length amount of bytes to snarf
1309    * @return Last <code>length</code> bytes from <code>a</code>
1310    */
1311   public static byte [] tail(final byte [] a, final int length) {
1312     if (a.length < length) {
1313       return null;
1314     }
1315     byte [] result = new byte[length];
1316     System.arraycopy(a, a.length - length, result, 0, length);
1317     return result;
1318   }
1319 
1320   /**
1321    * @param a array
1322    * @param length new array size
1323    * @return Value in <code>a</code> plus <code>length</code> prepended 0 bytes
1324    */
1325   public static byte [] padHead(final byte [] a, final int length) {
1326     byte [] padding = new byte[length];
1327     for (int i = 0; i < length; i++) {
1328       padding[i] = 0;
1329     }
1330     return add(padding,a);
1331   }
1332 
1333   /**
1334    * @param a array
1335    * @param length new array size
1336    * @return Value in <code>a</code> plus <code>length</code> appended 0 bytes
1337    */
1338   public static byte [] padTail(final byte [] a, final int length) {
1339     byte [] padding = new byte[length];
1340     for (int i = 0; i < length; i++) {
1341       padding[i] = 0;
1342     }
1343     return add(a,padding);
1344   }
1345 
1346   /**
1347    * Split passed range.  Expensive operation relatively.  Uses BigInteger math.
1348    * Useful splitting ranges for MapReduce jobs.
1349    * @param a Beginning of range
1350    * @param b End of range
1351    * @param num Number of times to split range.  Pass 1 if you want to split
1352    * the range in two; i.e. one split.
1353    * @return Array of dividing values
1354    */
1355   public static byte [][] split(final byte [] a, final byte [] b, final int num) {
1356     return split(a, b, false, num);
1357   }
1358 
1359   /**
1360    * Split passed range.  Expensive operation relatively.  Uses BigInteger math.
1361    * Useful splitting ranges for MapReduce jobs.
1362    * @param a Beginning of range
1363    * @param b End of range
1364    * @param inclusive Whether the end of range is prefix-inclusive or is
1365    * considered an exclusive boundary.  Automatic splits are generally exclusive
1366    * and manual splits with an explicit range utilize an inclusive end of range.
1367    * @param num Number of times to split range.  Pass 1 if you want to split
1368    * the range in two; i.e. one split.
1369    * @return Array of dividing values
1370    */
1371   public static byte[][] split(final byte[] a, final byte[] b,
1372       boolean inclusive, final int num) {
1373     byte[][] ret = new byte[num + 2][];
1374     int i = 0;
1375     Iterable<byte[]> iter = iterateOnSplits(a, b, inclusive, num);
1376     if (iter == null)
1377       return null;
1378     for (byte[] elem : iter) {
1379       ret[i++] = elem;
1380     }
1381     return ret;
1382   }
1383 
1384   /**
1385    * Iterate over keys within the passed range, splitting at an [a,b) boundary.
1386    */
1387   public static Iterable<byte[]> iterateOnSplits(final byte[] a,
1388       final byte[] b, final int num)
1389   {
1390     return iterateOnSplits(a, b, false, num);
1391   }
1392 
1393   /**
1394    * Iterate over keys within the passed range.
1395    */
1396   public static Iterable<byte[]> iterateOnSplits(
1397       final byte[] a, final byte[]b, boolean inclusive, final int num)
1398   {
1399     byte [] aPadded;
1400     byte [] bPadded;
1401     if (a.length < b.length) {
1402       aPadded = padTail(a, b.length - a.length);
1403       bPadded = b;
1404     } else if (b.length < a.length) {
1405       aPadded = a;
1406       bPadded = padTail(b, a.length - b.length);
1407     } else {
1408       aPadded = a;
1409       bPadded = b;
1410     }
1411     if (compareTo(aPadded,bPadded) >= 0) {
1412       throw new IllegalArgumentException("b <= a");
1413     }
1414     if (num <= 0) {
1415       throw new IllegalArgumentException("num cannot be < 0");
1416     }
1417     byte [] prependHeader = {1, 0};
1418     final BigInteger startBI = new BigInteger(add(prependHeader, aPadded));
1419     final BigInteger stopBI = new BigInteger(add(prependHeader, bPadded));
1420     BigInteger diffBI = stopBI.subtract(startBI);
1421     if (inclusive) {
1422       diffBI = diffBI.add(BigInteger.ONE);
1423     }
1424     final BigInteger splitsBI = BigInteger.valueOf(num + 1);
1425     if(diffBI.compareTo(splitsBI) < 0) {
1426       return null;
1427     }
1428     final BigInteger intervalBI;
1429     try {
1430       intervalBI = diffBI.divide(splitsBI);
1431     } catch(Exception e) {
1432       LOG.error("Exception caught during division", e);
1433       return null;
1434     }
1435 
1436     final Iterator<byte[]> iterator = new Iterator<byte[]>() {
1437       private int i = -1;
1438 
1439       @Override
1440       public boolean hasNext() {
1441         return i < num+1;
1442       }
1443 
1444       @Override
1445       public byte[] next() {
1446         i++;
1447         if (i == 0) return a;
1448         if (i == num + 1) return b;
1449 
1450         BigInteger curBI = startBI.add(intervalBI.multiply(BigInteger.valueOf(i)));
1451         byte [] padded = curBI.toByteArray();
1452         if (padded[1] == 0)
1453           padded = tail(padded, padded.length - 2);
1454         else
1455           padded = tail(padded, padded.length - 1);
1456         return padded;
1457       }
1458 
1459       @Override
1460       public void remove() {
1461         throw new UnsupportedOperationException();
1462       }
1463 
1464     };
1465 
1466     return new Iterable<byte[]>() {
1467       @Override
1468       public Iterator<byte[]> iterator() {
1469         return iterator;
1470       }
1471     };
1472   }
1473 
1474   /**
1475    * @param bytes array to hash
1476    * @param offset offset to start from
1477    * @param length length to hash
1478    * */
1479   public static int hashCode(byte[] bytes, int offset, int length) {
1480     int hash = 1;
1481     for (int i = offset; i < offset + length; i++)
1482       hash = (31 * hash) + (int) bytes[i];
1483     return hash;
1484   }
1485 
1486   /**
1487    * @param t operands
1488    * @return Array of byte arrays made from passed array of Text
1489    */
1490   public static byte [][] toByteArrays(final String [] t) {
1491     byte [][] result = new byte[t.length][];
1492     for (int i = 0; i < t.length; i++) {
1493       result[i] = Bytes.toBytes(t[i]);
1494     }
1495     return result;
1496   }
1497 
1498   /**
1499    * @param column operand
1500    * @return A byte array of a byte array where first and only entry is
1501    * <code>column</code>
1502    */
1503   public static byte [][] toByteArrays(final String column) {
1504     return toByteArrays(toBytes(column));
1505   }
1506 
1507   /**
1508    * @param column operand
1509    * @return A byte array of a byte array where first and only entry is
1510    * <code>column</code>
1511    */
1512   public static byte [][] toByteArrays(final byte [] column) {
1513     byte [][] result = new byte[1][];
1514     result[0] = column;
1515     return result;
1516   }
1517 
1518   /**
1519    * Binary search for keys in indexes.
1520    *
1521    * @param arr array of byte arrays to search for
1522    * @param key the key you want to find
1523    * @param offset the offset in the key you want to find
1524    * @param length the length of the key
1525    * @param comparator a comparator to compare.
1526    * @return zero-based index of the key, if the key is present in the array.
1527    *         Otherwise, a value -(i + 1) such that the key is between arr[i -
1528    *         1] and arr[i] non-inclusively, where i is in [0, i], if we define
1529    *         arr[-1] = -Inf and arr[N] = Inf for an N-element array. The above
1530    *         means that this function can return 2N + 1 different values
1531    *         ranging from -(N + 1) to N - 1.
1532    */
1533   public static int binarySearch(byte [][]arr, byte []key, int offset,
1534       int length, RawComparator<byte []> comparator) {
1535     int low = 0;
1536     int high = arr.length - 1;
1537 
1538     while (low <= high) {
1539       int mid = (low+high) >>> 1;
1540       // we have to compare in this order, because the comparator order
1541       // has special logic when the 'left side' is a special key.
1542       int cmp = comparator.compare(key, offset, length,
1543           arr[mid], 0, arr[mid].length);
1544       // key lives above the midpoint
1545       if (cmp > 0)
1546         low = mid + 1;
1547       // key lives below the midpoint
1548       else if (cmp < 0)
1549         high = mid - 1;
1550       // BAM. how often does this really happen?
1551       else
1552         return mid;
1553     }
1554     return - (low+1);
1555   }
1556 
1557   /**
1558    * Bytewise binary increment/deincrement of long contained in byte array
1559    * on given amount.
1560    *
1561    * @param value - array of bytes containing long (length <= SIZEOF_LONG)
1562    * @param amount value will be incremented on (deincremented if negative)
1563    * @return array of bytes containing incremented long (length == SIZEOF_LONG)
1564    */
1565   public static byte [] incrementBytes(byte[] value, long amount)
1566   {
1567     byte[] val = value;
1568     if (val.length < SIZEOF_LONG) {
1569       // Hopefully this doesn't happen too often.
1570       byte [] newvalue;
1571       if (val[0] < 0) {
1572         newvalue = new byte[]{-1, -1, -1, -1, -1, -1, -1, -1};
1573       } else {
1574         newvalue = new byte[SIZEOF_LONG];
1575       }
1576       System.arraycopy(val, 0, newvalue, newvalue.length - val.length,
1577         val.length);
1578       val = newvalue;
1579     } else if (val.length > SIZEOF_LONG) {
1580       throw new IllegalArgumentException("Increment Bytes - value too big: " +
1581         val.length);
1582     }
1583     if(amount == 0) return val;
1584     if(val[0] < 0){
1585       return binaryIncrementNeg(val, amount);
1586     }
1587     return binaryIncrementPos(val, amount);
1588   }
1589 
1590   /* increment/deincrement for positive value */
1591   private static byte [] binaryIncrementPos(byte [] value, long amount) {
1592     long amo = amount;
1593     int sign = 1;
1594     if (amount < 0) {
1595       amo = -amount;
1596       sign = -1;
1597     }
1598     for(int i=0;i<value.length;i++) {
1599       int cur = ((int)amo % 256) * sign;
1600       amo = (amo >> 8);
1601       int val = value[value.length-i-1] & 0x0ff;
1602       int total = val + cur;
1603       if(total > 255) {
1604         amo += sign;
1605         total %= 256;
1606       } else if (total < 0) {
1607         amo -= sign;
1608       }
1609       value[value.length-i-1] = (byte)total;
1610       if (amo == 0) return value;
1611     }
1612     return value;
1613   }
1614 
1615   /* increment/deincrement for negative value */
1616   private static byte [] binaryIncrementNeg(byte [] value, long amount) {
1617     long amo = amount;
1618     int sign = 1;
1619     if (amount < 0) {
1620       amo = -amount;
1621       sign = -1;
1622     }
1623     for(int i=0;i<value.length;i++) {
1624       int cur = ((int)amo % 256) * sign;
1625       amo = (amo >> 8);
1626       int val = ((~value[value.length-i-1]) & 0x0ff) + 1;
1627       int total = cur - val;
1628       if(total >= 0) {
1629         amo += sign;
1630       } else if (total < -256) {
1631         amo -= sign;
1632         total %= 256;
1633       }
1634       value[value.length-i-1] = (byte)total;
1635       if (amo == 0) return value;
1636     }
1637     return value;
1638   }
1639 
1640   /**
1641    * Writes a string as a fixed-size field, padded with zeros.
1642    */
1643   public static void writeStringFixedSize(final DataOutput out, String s,
1644       int size) throws IOException {
1645     byte[] b = toBytes(s);
1646     if (b.length > size) {
1647       throw new IOException("Trying to write " + b.length + " bytes (" +
1648           toStringBinary(b) + ") into a field of length " + size);
1649     }
1650 
1651     out.writeBytes(s);
1652     for (int i = 0; i < size - s.length(); ++i)
1653       out.writeByte(0);
1654   }
1655 
1656   /**
1657    * Reads a fixed-size field and interprets it as a string padded with zeros.
1658    */
1659   public static String readStringFixedSize(final DataInput in, int size)
1660       throws IOException {
1661     byte[] b = new byte[size];
1662     in.readFully(b);
1663     int n = b.length;
1664     while (n > 0 && b[n - 1] == 0)
1665       --n;
1666 
1667     return toString(b, 0, n);
1668   }
1669 
1670 }