1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
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
50
51
52
53 public class Bytes {
54
55 private static final Log LOG = LogFactory.getLog(Bytes.class);
56
57
58
59
60 public static final int SIZEOF_BOOLEAN = Byte.SIZE / Byte.SIZE;
61
62
63
64
65 public static final int SIZEOF_BYTE = SIZEOF_BOOLEAN;
66
67
68
69
70 public static final int SIZEOF_CHAR = Character.SIZE / Byte.SIZE;
71
72
73
74
75 public static final int SIZEOF_DOUBLE = Double.SIZE / Byte.SIZE;
76
77
78
79
80 public static final int SIZEOF_FLOAT = Float.SIZE / Byte.SIZE;
81
82
83
84
85 public static final int SIZEOF_INT = Integer.SIZE / Byte.SIZE;
86
87
88
89
90 public static final int SIZEOF_LONG = Long.SIZE / Byte.SIZE;
91
92
93
94
95 public static final int SIZEOF_SHORT = Short.SIZE / Byte.SIZE;
96
97
98
99
100
101
102
103
104 public static final int ESTIMATED_HEAP_TAX = 16;
105
106
107
108
109 public static class ByteArrayComparator implements RawComparator<byte []> {
110
111
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
127
128 public static Comparator<byte []> BYTES_COMPARATOR =
129 new ByteArrayComparator();
130
131
132
133
134 public static RawComparator<byte []> BYTES_RAWCOMPARATOR =
135 new ByteArrayComparator();
136
137
138
139
140
141
142
143 public static byte [] readByteArray(final DataInput in)
144 throws IOException {
145 int len = WritableUtils.readVInt(in);
146 if (len < 0) {
147 throw new NegativeArraySizeException(Integer.toString(len));
148 }
149 byte [] result = new byte[len];
150 in.readFully(result, 0, len);
151 return result;
152 }
153
154
155
156
157
158
159
160 public static byte [] readByteArrayThrowsRuntime(final DataInput in) {
161 try {
162 return readByteArray(in);
163 } catch (Exception e) {
164 throw new RuntimeException(e);
165 }
166 }
167
168
169
170
171
172
173
174 public static void writeByteArray(final DataOutput out, final byte [] b)
175 throws IOException {
176 if(b == null) {
177 WritableUtils.writeVInt(out, 0);
178 } else {
179 writeByteArray(out, b, 0, b.length);
180 }
181 }
182
183
184
185
186
187
188
189
190
191 public static void writeByteArray(final DataOutput out, final byte [] b,
192 final int offset, final int length)
193 throws IOException {
194 WritableUtils.writeVInt(out, length);
195 out.write(b, offset, length);
196 }
197
198
199
200
201
202
203
204
205
206
207 public static int writeByteArray(final byte [] tgt, final int tgtOffset,
208 final byte [] src, final int srcOffset, final int srcLength) {
209 byte [] vint = vintToBytes(srcLength);
210 System.arraycopy(vint, 0, tgt, tgtOffset, vint.length);
211 int offset = tgtOffset + vint.length;
212 System.arraycopy(src, srcOffset, tgt, offset, srcLength);
213 return offset + srcLength;
214 }
215
216
217
218
219
220
221
222
223
224
225 public static int putBytes(byte[] tgtBytes, int tgtOffset, byte[] srcBytes,
226 int srcOffset, int srcLength) {
227 System.arraycopy(srcBytes, srcOffset, tgtBytes, tgtOffset, srcLength);
228 return tgtOffset + srcLength;
229 }
230
231
232
233
234
235
236
237
238 public static int putByte(byte[] bytes, int offset, byte b) {
239 bytes[offset] = b;
240 return offset + 1;
241 }
242
243
244
245
246
247
248 public static byte[] toBytes(ByteBuffer bb) {
249 int length = bb.limit();
250 byte [] result = new byte[length];
251 System.arraycopy(bb.array(), bb.arrayOffset(), result, 0, length);
252 return result;
253 }
254
255
256
257
258
259 public static String toString(final byte [] b) {
260 if (b == null) {
261 return null;
262 }
263 return toString(b, 0, b.length);
264 }
265
266
267
268
269
270
271
272 public static String toString(final byte [] b1,
273 String sep,
274 final byte [] b2) {
275 return toString(b1, 0, b1.length) + sep + toString(b2, 0, b2.length);
276 }
277
278
279
280
281
282
283
284
285
286
287
288 public static String toString(final byte [] b, int off, int len) {
289 if (b == null) {
290 return null;
291 }
292 if (len == 0) {
293 return "";
294 }
295 try {
296 return new String(b, off, len, HConstants.UTF8_ENCODING);
297 } catch (UnsupportedEncodingException e) {
298 LOG.error("UTF-8 not supported?", e);
299 return null;
300 }
301 }
302
303
304
305
306
307
308
309
310 public static String toStringBinary(final byte [] b) {
311 if (b == null)
312 return "null";
313 return toStringBinary(b, 0, b.length);
314 }
315
316
317
318
319
320
321
322
323 public static String toStringBinary(ByteBuffer buf) {
324 if (buf == null)
325 return "null";
326 return toStringBinary(buf.array(), buf.arrayOffset(), buf.limit());
327 }
328
329
330
331
332
333
334
335
336
337
338
339 public static String toStringBinary(final byte [] b, int off, int len) {
340 StringBuilder result = new StringBuilder();
341 try {
342 String first = new String(b, off, len, "ISO-8859-1");
343 for (int i = 0; i < first.length() ; ++i ) {
344 int ch = first.charAt(i) & 0xFF;
345 if ( (ch >= '0' && ch <= '9')
346 || (ch >= 'A' && ch <= 'Z')
347 || (ch >= 'a' && ch <= 'z')
348 || " `~!@#$%^&*()-_=+[]{}\\|;:'\",.<>/?".indexOf(ch) >= 0 ) {
349 result.append(first.charAt(i));
350 } else {
351 result.append(String.format("\\x%02X", ch));
352 }
353 }
354 } catch (UnsupportedEncodingException e) {
355 LOG.error("ISO-8859-1 not supported?", e);
356 }
357 return result.toString();
358 }
359
360 private static boolean isHexDigit(char c) {
361 return
362 (c >= 'A' && c <= 'F') ||
363 (c >= '0' && c <= '9');
364 }
365
366
367
368
369
370
371
372 public static byte toBinaryFromHex(byte ch) {
373 if ( ch >= 'A' && ch <= 'F' )
374 return (byte) ((byte)10 + (byte) (ch - 'A'));
375
376 return (byte) (ch - '0');
377 }
378
379 public static byte [] toBytesBinary(String in) {
380
381 byte [] b = new byte[in.length()];
382 int size = 0;
383 for (int i = 0; i < in.length(); ++i) {
384 char ch = in.charAt(i);
385 if (ch == '\\') {
386
387 char next = in.charAt(i+1);
388 if (next != 'x') {
389
390 b[size++] = (byte)ch;
391 continue;
392 }
393
394 char hd1 = in.charAt(i+2);
395 char hd2 = in.charAt(i+3);
396
397
398 if (!isHexDigit(hd1) ||
399 !isHexDigit(hd2)) {
400
401 continue;
402 }
403
404 byte d = (byte) ((toBinaryFromHex((byte)hd1) << 4) + toBinaryFromHex((byte)hd2));
405
406 b[size++] = d;
407 i += 3;
408 } else {
409 b[size++] = (byte) ch;
410 }
411 }
412
413 byte [] b2 = new byte[size];
414 System.arraycopy(b, 0, b2, 0, size);
415 return b2;
416 }
417
418
419
420
421
422
423 public static byte[] toBytes(String s) {
424 try {
425 return s.getBytes(HConstants.UTF8_ENCODING);
426 } catch (UnsupportedEncodingException e) {
427 LOG.error("UTF-8 not supported?", e);
428 return null;
429 }
430 }
431
432
433
434
435
436
437
438
439 public static byte [] toBytes(final boolean b) {
440 return new byte[] { b ? (byte) -1 : (byte) 0 };
441 }
442
443
444
445
446
447
448 public static boolean toBoolean(final byte [] b) {
449 if (b.length != 1) {
450 throw new IllegalArgumentException("Array has wrong size: " + b.length);
451 }
452 return b[0] != (byte) 0;
453 }
454
455
456
457
458
459
460
461 public static byte[] toBytes(long val) {
462 byte [] b = new byte[8];
463 for (int i = 7; i > 0; i--) {
464 b[i] = (byte) val;
465 val >>>= 8;
466 }
467 b[0] = (byte) val;
468 return b;
469 }
470
471
472
473
474
475
476
477 public static long toLong(byte[] bytes) {
478 return toLong(bytes, 0, SIZEOF_LONG);
479 }
480
481
482
483
484
485
486
487
488
489 public static long toLong(byte[] bytes, int offset) {
490 return toLong(bytes, offset, SIZEOF_LONG);
491 }
492
493
494
495
496
497
498
499
500
501
502
503 public static long toLong(byte[] bytes, int offset, final int length) {
504 if (length != SIZEOF_LONG || offset + length > bytes.length) {
505 throw explainWrongLengthOrOffset(bytes, offset, length, SIZEOF_LONG);
506 }
507 long l = 0;
508 for(int i = offset; i < offset + length; i++) {
509 l <<= 8;
510 l ^= bytes[i] & 0xFF;
511 }
512 return l;
513 }
514
515 private static IllegalArgumentException
516 explainWrongLengthOrOffset(final byte[] bytes,
517 final int offset,
518 final int length,
519 final int expectedLength) {
520 String reason;
521 if (length != expectedLength) {
522 reason = "Wrong length: " + length + ", expected " + expectedLength;
523 } else {
524 reason = "offset (" + offset + ") + length (" + length + ") exceed the"
525 + " capacity of the array: " + bytes.length;
526 }
527 return new IllegalArgumentException(reason);
528 }
529
530
531
532
533
534
535
536
537
538
539 public static int putLong(byte[] bytes, int offset, long val) {
540 if (bytes.length - offset < SIZEOF_LONG) {
541 throw new IllegalArgumentException("Not enough room to put a long at"
542 + " offset " + offset + " in a " + bytes.length + " byte array");
543 }
544 for(int i = offset + 7; i > offset; i--) {
545 bytes[i] = (byte) val;
546 val >>>= 8;
547 }
548 bytes[offset] = (byte) val;
549 return offset + SIZEOF_LONG;
550 }
551
552
553
554
555
556
557 public static float toFloat(byte [] bytes) {
558 return toFloat(bytes, 0);
559 }
560
561
562
563
564
565
566
567 public static float toFloat(byte [] bytes, int offset) {
568 return Float.intBitsToFloat(toInt(bytes, offset, SIZEOF_INT));
569 }
570
571
572
573
574
575
576
577 public static int putFloat(byte [] bytes, int offset, float f) {
578 return putInt(bytes, offset, Float.floatToRawIntBits(f));
579 }
580
581
582
583
584
585 public static byte [] toBytes(final float f) {
586
587 return Bytes.toBytes(Float.floatToRawIntBits(f));
588 }
589
590
591
592
593
594 public static double toDouble(final byte [] bytes) {
595 return toDouble(bytes, 0);
596 }
597
598
599
600
601
602
603 public static double toDouble(final byte [] bytes, final int offset) {
604 return Double.longBitsToDouble(toLong(bytes, offset, SIZEOF_LONG));
605 }
606
607
608
609
610
611
612
613 public static int putDouble(byte [] bytes, int offset, double d) {
614 return putLong(bytes, offset, Double.doubleToLongBits(d));
615 }
616
617
618
619
620
621
622
623
624 public static byte [] toBytes(final double d) {
625
626 return Bytes.toBytes(Double.doubleToRawLongBits(d));
627 }
628
629
630
631
632
633
634 public static byte[] toBytes(int val) {
635 byte [] b = new byte[4];
636 for(int i = 3; i > 0; i--) {
637 b[i] = (byte) val;
638 val >>>= 8;
639 }
640 b[0] = (byte) val;
641 return b;
642 }
643
644
645
646
647
648
649 public static int toInt(byte[] bytes) {
650 return toInt(bytes, 0, SIZEOF_INT);
651 }
652
653
654
655
656
657
658
659 public static int toInt(byte[] bytes, int offset) {
660 return toInt(bytes, offset, SIZEOF_INT);
661 }
662
663
664
665
666
667
668
669
670
671
672 public static int toInt(byte[] bytes, int offset, final int length) {
673 if (length != SIZEOF_INT || offset + length > bytes.length) {
674 throw explainWrongLengthOrOffset(bytes, offset, length, SIZEOF_INT);
675 }
676 int n = 0;
677 for(int i = offset; i < (offset + length); i++) {
678 n <<= 8;
679 n ^= bytes[i] & 0xFF;
680 }
681 return n;
682 }
683
684
685
686
687
688
689
690
691
692
693 public static int putInt(byte[] bytes, int offset, int val) {
694 if (bytes.length - offset < SIZEOF_INT) {
695 throw new IllegalArgumentException("Not enough room to put an int at"
696 + " offset " + offset + " in a " + bytes.length + " byte array");
697 }
698 for(int i= offset + 3; i > offset; i--) {
699 bytes[i] = (byte) val;
700 val >>>= 8;
701 }
702 bytes[offset] = (byte) val;
703 return offset + SIZEOF_INT;
704 }
705
706
707
708
709
710
711 public static byte[] toBytes(short val) {
712 byte[] b = new byte[SIZEOF_SHORT];
713 b[1] = (byte) val;
714 val >>= 8;
715 b[0] = (byte) val;
716 return b;
717 }
718
719
720
721
722
723
724 public static short toShort(byte[] bytes) {
725 return toShort(bytes, 0, SIZEOF_SHORT);
726 }
727
728
729
730
731
732
733
734 public static short toShort(byte[] bytes, int offset) {
735 return toShort(bytes, offset, SIZEOF_SHORT);
736 }
737
738
739
740
741
742
743
744
745
746
747 public static short toShort(byte[] bytes, int offset, final int length) {
748 if (length != SIZEOF_SHORT || offset + length > bytes.length) {
749 throw explainWrongLengthOrOffset(bytes, offset, length, SIZEOF_SHORT);
750 }
751 short n = 0;
752 n ^= bytes[offset] & 0xFF;
753 n <<= 8;
754 n ^= bytes[offset+1] & 0xFF;
755 return n;
756 }
757
758
759
760
761
762
763
764 public static byte[] getBytes(ByteBuffer buf) {
765 int savedPos = buf.position();
766 byte [] newBytes = new byte[buf.remaining()];
767 buf.get(newBytes);
768 buf.position(savedPos);
769 return newBytes;
770 }
771
772
773
774
775
776
777
778
779
780
781 public static int putShort(byte[] bytes, int offset, short val) {
782 if (bytes.length - offset < SIZEOF_SHORT) {
783 throw new IllegalArgumentException("Not enough room to put a short at"
784 + " offset " + offset + " in a " + bytes.length + " byte array");
785 }
786 bytes[offset+1] = (byte) val;
787 val >>= 8;
788 bytes[offset] = (byte) val;
789 return offset + SIZEOF_SHORT;
790 }
791
792
793
794
795
796
797
798 public static byte[] toBytes(BigDecimal val) {
799 byte[] valueBytes = val.unscaledValue().toByteArray();
800 byte[] result = new byte[valueBytes.length + SIZEOF_INT];
801 int offset = putInt(result, 0, val.scale());
802 putBytes(result, offset, valueBytes, 0, valueBytes.length);
803 return result;
804 }
805
806
807
808
809
810
811
812
813 public static BigDecimal toBigDecimal(byte[] bytes) {
814 return toBigDecimal(bytes, 0, bytes.length);
815 }
816
817
818
819
820
821
822
823
824
825 public static BigDecimal toBigDecimal(byte[] bytes, int offset, final int length) {
826 if (bytes == null || length < SIZEOF_INT + 1 ||
827 (offset + length > bytes.length)) {
828 return null;
829 }
830
831 int scale = toInt(bytes, offset);
832 byte[] tcBytes = new byte[length - SIZEOF_INT];
833 System.arraycopy(bytes, offset + SIZEOF_INT, tcBytes, 0, length - SIZEOF_INT);
834 return new BigDecimal(new BigInteger(tcBytes), scale);
835 }
836
837
838
839
840
841
842
843
844
845 public static int putBigDecimal(byte[] bytes, int offset, BigDecimal val) {
846 if (bytes == null) {
847 return offset;
848 }
849
850 byte[] valueBytes = val.unscaledValue().toByteArray();
851 byte[] result = new byte[valueBytes.length + SIZEOF_INT];
852 offset = putInt(result, offset, val.scale());
853 return putBytes(result, offset, valueBytes, 0, valueBytes.length);
854 }
855
856
857
858
859
860 public static byte [] vintToBytes(final long vint) {
861 long i = vint;
862 int size = WritableUtils.getVIntSize(i);
863 byte [] result = new byte[size];
864 int offset = 0;
865 if (i >= -112 && i <= 127) {
866 result[offset] = (byte) i;
867 return result;
868 }
869
870 int len = -112;
871 if (i < 0) {
872 i ^= -1L;
873 len = -120;
874 }
875
876 long tmp = i;
877 while (tmp != 0) {
878 tmp = tmp >> 8;
879 len--;
880 }
881
882 result[offset++] = (byte) len;
883
884 len = (len < -120) ? -(len + 120) : -(len + 112);
885
886 for (int idx = len; idx != 0; idx--) {
887 int shiftbits = (idx - 1) * 8;
888 long mask = 0xFFL << shiftbits;
889 result[offset++] = (byte)((i & mask) >> shiftbits);
890 }
891 return result;
892 }
893
894
895
896
897
898 public static long bytesToVint(final byte [] buffer) {
899 int offset = 0;
900 byte firstByte = buffer[offset++];
901 int len = WritableUtils.decodeVIntSize(firstByte);
902 if (len == 1) {
903 return firstByte;
904 }
905 long i = 0;
906 for (int idx = 0; idx < len-1; idx++) {
907 byte b = buffer[offset++];
908 i = i << 8;
909 i = i | (b & 0xFF);
910 }
911 return (WritableUtils.isNegativeVInt(firstByte) ? ~i : i);
912 }
913
914
915
916
917
918
919
920
921 public static long readVLong(final byte [] buffer, final int offset)
922 throws IOException {
923 byte firstByte = buffer[offset];
924 int len = WritableUtils.decodeVIntSize(firstByte);
925 if (len == 1) {
926 return firstByte;
927 }
928 long i = 0;
929 for (int idx = 0; idx < len-1; idx++) {
930 byte b = buffer[offset + 1 + idx];
931 i = i << 8;
932 i = i | (b & 0xFF);
933 }
934 return (WritableUtils.isNegativeVInt(firstByte) ? ~i : i);
935 }
936
937
938
939
940
941
942 public static int compareTo(final byte [] left, final byte [] right) {
943 return LexicographicalComparerHolder.BEST_COMPARER.
944 compareTo(left, 0, left.length, right, 0, right.length);
945 }
946
947
948
949
950
951
952
953
954
955
956
957
958 public static int compareTo(byte[] buffer1, int offset1, int length1,
959 byte[] buffer2, int offset2, int length2) {
960 return LexicographicalComparerHolder.BEST_COMPARER.
961 compareTo(buffer1, offset1, length1, buffer2, offset2, length2);
962 }
963
964 interface Comparer<T> {
965 abstract public int compareTo(T buffer1, int offset1, int length1,
966 T buffer2, int offset2, int length2);
967 }
968
969 @VisibleForTesting
970 static Comparer<byte[]> lexicographicalComparerJavaImpl() {
971 return LexicographicalComparerHolder.PureJavaComparer.INSTANCE;
972 }
973
974
975
976
977
978
979
980
981 @VisibleForTesting
982 static class LexicographicalComparerHolder {
983 static final String UNSAFE_COMPARER_NAME =
984 LexicographicalComparerHolder.class.getName() + "$UnsafeComparer";
985
986 static final Comparer<byte[]> BEST_COMPARER = getBestComparer();
987
988
989
990
991 static Comparer<byte[]> getBestComparer() {
992 try {
993 Class<?> theClass = Class.forName(UNSAFE_COMPARER_NAME);
994
995
996 @SuppressWarnings("unchecked")
997 Comparer<byte[]> comparer =
998 (Comparer<byte[]>) theClass.getEnumConstants()[0];
999 return comparer;
1000 } catch (Throwable t) {
1001 return lexicographicalComparerJavaImpl();
1002 }
1003 }
1004
1005 enum PureJavaComparer implements Comparer<byte[]> {
1006 INSTANCE;
1007
1008 @Override
1009 public int compareTo(byte[] buffer1, int offset1, int length1,
1010 byte[] buffer2, int offset2, int length2) {
1011
1012 if (buffer1 == buffer2 &&
1013 offset1 == offset2 &&
1014 length1 == length2) {
1015 return 0;
1016 }
1017
1018 int end1 = offset1 + length1;
1019 int end2 = offset2 + length2;
1020 for (int i = offset1, j = offset2; i < end1 && j < end2; i++, j++) {
1021 int a = (buffer1[i] & 0xff);
1022 int b = (buffer2[j] & 0xff);
1023 if (a != b) {
1024 return a - b;
1025 }
1026 }
1027 return length1 - length2;
1028 }
1029 }
1030
1031 @VisibleForTesting
1032 enum UnsafeComparer implements Comparer<byte[]> {
1033 INSTANCE;
1034
1035 static final Unsafe theUnsafe;
1036
1037
1038 static final int BYTE_ARRAY_BASE_OFFSET;
1039
1040 static {
1041 theUnsafe = (Unsafe) AccessController.doPrivileged(
1042 new PrivilegedAction<Object>() {
1043 @Override
1044 public Object run() {
1045 try {
1046 Field f = Unsafe.class.getDeclaredField("theUnsafe");
1047 f.setAccessible(true);
1048 return f.get(null);
1049 } catch (NoSuchFieldException e) {
1050
1051
1052 throw new Error();
1053 } catch (IllegalAccessException e) {
1054 throw new Error();
1055 }
1056 }
1057 });
1058
1059 BYTE_ARRAY_BASE_OFFSET = theUnsafe.arrayBaseOffset(byte[].class);
1060
1061
1062 if (theUnsafe.arrayIndexScale(byte[].class) != 1) {
1063 throw new AssertionError();
1064 }
1065 }
1066
1067 static final boolean littleEndian =
1068 ByteOrder.nativeOrder().equals(ByteOrder.LITTLE_ENDIAN);
1069
1070
1071
1072
1073
1074 static boolean lessThanUnsigned(long x1, long x2) {
1075 return (x1 + Long.MIN_VALUE) < (x2 + Long.MIN_VALUE);
1076 }
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089 @Override
1090 public int compareTo(byte[] buffer1, int offset1, int length1,
1091 byte[] buffer2, int offset2, int length2) {
1092
1093 if (buffer1 == buffer2 &&
1094 offset1 == offset2 &&
1095 length1 == length2) {
1096 return 0;
1097 }
1098 int minLength = Math.min(length1, length2);
1099 int minWords = minLength / SIZEOF_LONG;
1100 int offset1Adj = offset1 + BYTE_ARRAY_BASE_OFFSET;
1101 int offset2Adj = offset2 + BYTE_ARRAY_BASE_OFFSET;
1102
1103
1104
1105
1106
1107
1108 for (int i = 0; i < minWords * SIZEOF_LONG; i += SIZEOF_LONG) {
1109 long lw = theUnsafe.getLong(buffer1, offset1Adj + (long) i);
1110 long rw = theUnsafe.getLong(buffer2, offset2Adj + (long) i);
1111 long diff = lw ^ rw;
1112
1113 if (diff != 0) {
1114 if (!littleEndian) {
1115 return lessThanUnsigned(lw, rw) ? -1 : 1;
1116 }
1117
1118
1119 int n = 0;
1120 int y;
1121 int x = (int) diff;
1122 if (x == 0) {
1123 x = (int) (diff >>> 32);
1124 n = 32;
1125 }
1126
1127 y = x << 16;
1128 if (y == 0) {
1129 n += 16;
1130 } else {
1131 x = y;
1132 }
1133
1134 y = x << 8;
1135 if (y == 0) {
1136 n += 8;
1137 }
1138 return (int) (((lw >>> n) & 0xFFL) - ((rw >>> n) & 0xFFL));
1139 }
1140 }
1141
1142
1143 for (int i = minWords * SIZEOF_LONG; i < minLength; i++) {
1144 int a = (buffer1[offset1 + i] & 0xff);
1145 int b = (buffer2[offset2 + i] & 0xff);
1146 if (a != b) {
1147 return a - b;
1148 }
1149 }
1150 return length1 - length2;
1151 }
1152 }
1153 }
1154
1155
1156
1157
1158
1159
1160 public static boolean equals(final byte [] left, final byte [] right) {
1161
1162
1163 if (left == right) return true;
1164 if (left == null || right == null) return false;
1165 if (left.length != right.length) return false;
1166 if (left.length == 0) return true;
1167
1168
1169
1170
1171 if (left[left.length - 1] != right[right.length - 1]) return false;
1172
1173 return compareTo(left, right) == 0;
1174 }
1175
1176 public static boolean equals(final byte[] left, int leftOffset, int leftLen,
1177 final byte[] right, int rightOffset, int rightLen) {
1178
1179 if (left == right &&
1180 leftOffset == rightOffset &&
1181 leftLen == rightLen) {
1182 return true;
1183 }
1184
1185 if (leftLen != rightLen) {
1186 return false;
1187 }
1188 if (leftLen == 0) {
1189 return true;
1190 }
1191
1192
1193
1194
1195 if (left[leftOffset + leftLen - 1] != right[rightOffset + rightLen - 1]) return false;
1196
1197 return LexicographicalComparerHolder.BEST_COMPARER.
1198 compareTo(left, leftOffset, leftLen, right, rightOffset, rightLen) == 0;
1199 }
1200
1201
1202
1203
1204
1205
1206 public static boolean startsWith(byte[] bytes, byte[] prefix) {
1207 return bytes != null && prefix != null &&
1208 bytes.length >= prefix.length &&
1209 LexicographicalComparerHolder.BEST_COMPARER.
1210 compareTo(bytes, 0, prefix.length, prefix, 0, prefix.length) == 0;
1211 }
1212
1213
1214
1215
1216
1217
1218
1219 public static int hashCode(final byte [] b) {
1220 return hashCode(b, b.length);
1221 }
1222
1223
1224
1225
1226
1227
1228
1229
1230 public static int hashCode(final byte [] b, final int length) {
1231 return WritableComparator.hashBytes(b, length);
1232 }
1233
1234
1235
1236
1237
1238
1239 public static Integer mapKey(final byte [] b) {
1240 return hashCode(b);
1241 }
1242
1243
1244
1245
1246
1247
1248
1249 public static Integer mapKey(final byte [] b, final int length) {
1250 return hashCode(b, length);
1251 }
1252
1253
1254
1255
1256
1257
1258 public static byte [] add(final byte [] a, final byte [] b) {
1259 return add(a, b, HConstants.EMPTY_BYTE_ARRAY);
1260 }
1261
1262
1263
1264
1265
1266
1267
1268 public static byte [] add(final byte [] a, final byte [] b, final byte [] c) {
1269 byte [] result = new byte[a.length + b.length + c.length];
1270 System.arraycopy(a, 0, result, 0, a.length);
1271 System.arraycopy(b, 0, result, a.length, b.length);
1272 System.arraycopy(c, 0, result, a.length + b.length, c.length);
1273 return result;
1274 }
1275
1276
1277
1278
1279
1280
1281 public static byte [] head(final byte [] a, final int length) {
1282 if (a.length < length) {
1283 return null;
1284 }
1285 byte [] result = new byte[length];
1286 System.arraycopy(a, 0, result, 0, length);
1287 return result;
1288 }
1289
1290
1291
1292
1293
1294
1295 public static byte [] tail(final byte [] a, final int length) {
1296 if (a.length < length) {
1297 return null;
1298 }
1299 byte [] result = new byte[length];
1300 System.arraycopy(a, a.length - length, result, 0, length);
1301 return result;
1302 }
1303
1304
1305
1306
1307
1308
1309 public static byte [] padHead(final byte [] a, final int length) {
1310 byte [] padding = new byte[length];
1311 for (int i = 0; i < length; i++) {
1312 padding[i] = 0;
1313 }
1314 return add(padding,a);
1315 }
1316
1317
1318
1319
1320
1321
1322 public static byte [] padTail(final byte [] a, final int length) {
1323 byte [] padding = new byte[length];
1324 for (int i = 0; i < length; i++) {
1325 padding[i] = 0;
1326 }
1327 return add(a,padding);
1328 }
1329
1330
1331
1332
1333
1334
1335
1336
1337
1338
1339 public static byte [][] split(final byte [] a, final byte [] b, final int num) {
1340 byte[][] ret = new byte[num+2][];
1341 int i = 0;
1342 Iterable<byte[]> iter = iterateOnSplits(a, b, num);
1343 if (iter == null) return null;
1344 for (byte[] elem : iter) {
1345 ret[i++] = elem;
1346 }
1347 return ret;
1348 }
1349
1350
1351
1352
1353 public static Iterable<byte[]> iterateOnSplits(
1354 final byte[] a, final byte[]b, final int num)
1355 {
1356 byte [] aPadded;
1357 byte [] bPadded;
1358 if (a.length < b.length) {
1359 aPadded = padTail(a, b.length - a.length);
1360 bPadded = b;
1361 } else if (b.length < a.length) {
1362 aPadded = a;
1363 bPadded = padTail(b, a.length - b.length);
1364 } else {
1365 aPadded = a;
1366 bPadded = b;
1367 }
1368 if (compareTo(aPadded,bPadded) >= 0) {
1369 throw new IllegalArgumentException("b <= a");
1370 }
1371 if (num <= 0) {
1372 throw new IllegalArgumentException("num cannot be < 0");
1373 }
1374 byte [] prependHeader = {1, 0};
1375 final BigInteger startBI = new BigInteger(add(prependHeader, aPadded));
1376 final BigInteger stopBI = new BigInteger(add(prependHeader, bPadded));
1377 final BigInteger diffBI = stopBI.subtract(startBI);
1378 final BigInteger splitsBI = BigInteger.valueOf(num + 1);
1379 if(diffBI.compareTo(splitsBI) < 0) {
1380 return null;
1381 }
1382 final BigInteger intervalBI;
1383 try {
1384 intervalBI = diffBI.divide(splitsBI);
1385 } catch(Exception e) {
1386 LOG.error("Exception caught during division", e);
1387 return null;
1388 }
1389
1390 final Iterator<byte[]> iterator = new Iterator<byte[]>() {
1391 private int i = -1;
1392
1393 @Override
1394 public boolean hasNext() {
1395 return i < num+1;
1396 }
1397
1398 @Override
1399 public byte[] next() {
1400 i++;
1401 if (i == 0) return a;
1402 if (i == num + 1) return b;
1403
1404 BigInteger curBI = startBI.add(intervalBI.multiply(BigInteger.valueOf(i)));
1405 byte [] padded = curBI.toByteArray();
1406 if (padded[1] == 0)
1407 padded = tail(padded, padded.length - 2);
1408 else
1409 padded = tail(padded, padded.length - 1);
1410 return padded;
1411 }
1412
1413 @Override
1414 public void remove() {
1415 throw new UnsupportedOperationException();
1416 }
1417
1418 };
1419
1420 return new Iterable<byte[]>() {
1421 @Override
1422 public Iterator<byte[]> iterator() {
1423 return iterator;
1424 }
1425 };
1426 }
1427
1428
1429
1430
1431
1432 public static byte [][] toByteArrays(final String [] t) {
1433 byte [][] result = new byte[t.length][];
1434 for (int i = 0; i < t.length; i++) {
1435 result[i] = Bytes.toBytes(t[i]);
1436 }
1437 return result;
1438 }
1439
1440
1441
1442
1443
1444
1445 public static byte [][] toByteArrays(final String column) {
1446 return toByteArrays(toBytes(column));
1447 }
1448
1449
1450
1451
1452
1453
1454 public static byte [][] toByteArrays(final byte [] column) {
1455 byte [][] result = new byte[1][];
1456 result[0] = column;
1457 return result;
1458 }
1459
1460
1461
1462
1463
1464
1465
1466
1467
1468
1469
1470
1471
1472
1473
1474
1475 public static int binarySearch(byte [][]arr, byte []key, int offset,
1476 int length, RawComparator<byte []> comparator) {
1477 int low = 0;
1478 int high = arr.length - 1;
1479
1480 while (low <= high) {
1481 int mid = (low+high) >>> 1;
1482
1483
1484 int cmp = comparator.compare(key, offset, length,
1485 arr[mid], 0, arr[mid].length);
1486
1487 if (cmp > 0)
1488 low = mid + 1;
1489
1490 else if (cmp < 0)
1491 high = mid - 1;
1492
1493 else
1494 return mid;
1495 }
1496 return - (low+1);
1497 }
1498
1499
1500
1501
1502
1503
1504
1505
1506
1507 public static byte [] incrementBytes(byte[] value, long amount)
1508 {
1509 byte[] val = value;
1510 if (val.length < SIZEOF_LONG) {
1511
1512 byte [] newvalue;
1513 if (val[0] < 0) {
1514 newvalue = new byte[]{-1, -1, -1, -1, -1, -1, -1, -1};
1515 } else {
1516 newvalue = new byte[SIZEOF_LONG];
1517 }
1518 System.arraycopy(val, 0, newvalue, newvalue.length - val.length,
1519 val.length);
1520 val = newvalue;
1521 } else if (val.length > SIZEOF_LONG) {
1522 throw new IllegalArgumentException("Increment Bytes - value too big: " +
1523 val.length);
1524 }
1525 if(amount == 0) return val;
1526 if(val[0] < 0){
1527 return binaryIncrementNeg(val, amount);
1528 }
1529 return binaryIncrementPos(val, amount);
1530 }
1531
1532
1533 private static byte [] binaryIncrementPos(byte [] value, long amount) {
1534 long amo = amount;
1535 int sign = 1;
1536 if (amount < 0) {
1537 amo = -amount;
1538 sign = -1;
1539 }
1540 for(int i=0;i<value.length;i++) {
1541 int cur = ((int)amo % 256) * sign;
1542 amo = (amo >> 8);
1543 int val = value[value.length-i-1] & 0x0ff;
1544 int total = val + cur;
1545 if(total > 255) {
1546 amo += sign;
1547 total %= 256;
1548 } else if (total < 0) {
1549 amo -= sign;
1550 }
1551 value[value.length-i-1] = (byte)total;
1552 if (amo == 0) return value;
1553 }
1554 return value;
1555 }
1556
1557
1558 private static byte [] binaryIncrementNeg(byte [] value, long amount) {
1559 long amo = amount;
1560 int sign = 1;
1561 if (amount < 0) {
1562 amo = -amount;
1563 sign = -1;
1564 }
1565 for(int i=0;i<value.length;i++) {
1566 int cur = ((int)amo % 256) * sign;
1567 amo = (amo >> 8);
1568 int val = ((~value[value.length-i-1]) & 0x0ff) + 1;
1569 int total = cur - val;
1570 if(total >= 0) {
1571 amo += sign;
1572 } else if (total < -256) {
1573 amo -= sign;
1574 total %= 256;
1575 }
1576 value[value.length-i-1] = (byte)total;
1577 if (amo == 0) return value;
1578 }
1579 return value;
1580 }
1581
1582
1583
1584
1585 public static void writeStringFixedSize(final DataOutput out, String s,
1586 int size) throws IOException {
1587 byte[] b = toBytes(s);
1588 if (b.length > size) {
1589 throw new IOException("Trying to write " + b.length + " bytes (" +
1590 toStringBinary(b) + ") into a field of length " + size);
1591 }
1592
1593 out.writeBytes(s);
1594 for (int i = 0; i < size - s.length(); ++i)
1595 out.writeByte(0);
1596 }
1597
1598
1599
1600
1601 public static String readStringFixedSize(final DataInput in, int size)
1602 throws IOException {
1603 byte[] b = new byte[size];
1604 in.readFully(b);
1605 int n = b.length;
1606 while (n > 0 && b[n - 1] == 0)
1607 --n;
1608
1609 return toString(b, 0, n);
1610 }
1611
1612 }