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
129
130
131
132
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;
145 }
146 if (l2 == 0) {
147 return -1;
148 }
149 return super.compare(b1, s1, l1, b2, s2, l2);
150 }
151 }
152
153
154
155
156 public static Comparator<byte []> BYTES_COMPARATOR =
157 new ByteArrayComparator();
158
159
160
161
162 public static RawComparator<byte []> BYTES_RAWCOMPARATOR =
163 new ByteArrayComparator();
164
165
166
167
168
169
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
184
185
186
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
198
199
200
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
213
214
215
216
217
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
228
229
230
231
232
233
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
246
247
248
249
250
251
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
261
262
263
264
265
266 public static int putByte(byte[] bytes, int offset, byte b) {
267 bytes[offset] = b;
268 return offset + 1;
269 }
270
271
272
273
274
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
285
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
296
297
298
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
308
309
310
311
312
313
314
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
333
334
335
336
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
346
347
348
349
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
359
360
361
362
363
364
365
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
391
392
393
394
395 public static byte toBinaryFromHex(byte ch) {
396 if ( ch >= 'A' && ch <= 'F' )
397 return (byte) ((byte)10 + (byte) (ch - 'A'));
398
399 return (byte) (ch - '0');
400 }
401
402 public static byte [] toBytesBinary(String in) {
403
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
410 char hd1 = in.charAt(i+2);
411 char hd2 = in.charAt(i+3);
412
413
414 if (!isHexDigit(hd1) ||
415 !isHexDigit(hd2)) {
416
417 continue;
418 }
419
420 byte d = (byte) ((toBinaryFromHex((byte)hd1) << 4) + toBinaryFromHex((byte)hd2));
421
422 b[size++] = d;
423 i += 3;
424 } else {
425 b[size++] = (byte) ch;
426 }
427 }
428
429 byte [] b2 = new byte[size];
430 System.arraycopy(b, 0, b2, 0, size);
431 return b2;
432 }
433
434
435
436
437
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
450
451
452
453
454
455 public static byte [] toBytes(final boolean b) {
456 return new byte[] { b ? (byte) -1 : (byte) 0 };
457 }
458
459
460
461
462
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
473
474
475
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
489
490
491
492
493 public static long toLong(byte[] bytes) {
494 return toLong(bytes, 0, SIZEOF_LONG);
495 }
496
497
498
499
500
501
502
503
504
505 public static long toLong(byte[] bytes, int offset) {
506 return toLong(bytes, offset, SIZEOF_LONG);
507 }
508
509
510
511
512
513
514
515
516
517
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
548
549
550
551
552
553
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
570
571
572
573 public static float toFloat(byte [] bytes) {
574 return toFloat(bytes, 0);
575 }
576
577
578
579
580
581
582
583 public static float toFloat(byte [] bytes, int offset) {
584 return Float.intBitsToFloat(toInt(bytes, offset, SIZEOF_INT));
585 }
586
587
588
589
590
591
592
593 public static int putFloat(byte [] bytes, int offset, float f) {
594 return putInt(bytes, offset, Float.floatToRawIntBits(f));
595 }
596
597
598
599
600
601 public static byte [] toBytes(final float f) {
602
603 return Bytes.toBytes(Float.floatToRawIntBits(f));
604 }
605
606
607
608
609
610 public static double toDouble(final byte [] bytes) {
611 return toDouble(bytes, 0);
612 }
613
614
615
616
617
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
625
626
627
628
629 public static int putDouble(byte [] bytes, int offset, double d) {
630 return putLong(bytes, offset, Double.doubleToLongBits(d));
631 }
632
633
634
635
636
637
638
639
640 public static byte [] toBytes(final double d) {
641
642 return Bytes.toBytes(Double.doubleToRawLongBits(d));
643 }
644
645
646
647
648
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
662
663
664
665 public static int toInt(byte[] bytes) {
666 return toInt(bytes, 0, SIZEOF_INT);
667 }
668
669
670
671
672
673
674
675 public static int toInt(byte[] bytes, int offset) {
676 return toInt(bytes, offset, SIZEOF_INT);
677 }
678
679
680
681
682
683
684
685
686
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
702
703
704
705
706
707
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
724
725
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
737
738
739
740 public static short toShort(byte[] bytes) {
741 return toShort(bytes, 0, SIZEOF_SHORT);
742 }
743
744
745
746
747
748
749
750 public static short toShort(byte[] bytes, int offset) {
751 return toShort(bytes, offset, SIZEOF_SHORT);
752 }
753
754
755
756
757
758
759
760
761
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
776
777
778
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
790
791
792
793
794
795
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
810
811
812
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
825
826
827
828
829 public static BigDecimal toBigDecimal(byte[] bytes) {
830 return toBigDecimal(bytes, 0, bytes.length);
831 }
832
833
834
835
836
837
838
839
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
855
856
857
858
859
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
874
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;
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
912
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
932
933
934
935
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
955
956
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
965
966
967
968
969
970
971
972
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
992
993
994
995
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
1005
1006
1007 static Comparer<byte[]> getBestComparer() {
1008 try {
1009 Class<?> theClass = Class.forName(UNSAFE_COMPARER_NAME);
1010
1011
1012 @SuppressWarnings("unchecked")
1013 Comparer<byte[]> comparer =
1014 (Comparer<byte[]>) theClass.getEnumConstants()[0];
1015 return comparer;
1016 } catch (Throwable t) {
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
1028 if (buffer1 == buffer2 &&
1029 offset1 == offset2 &&
1030 length1 == length2) {
1031 return 0;
1032 }
1033
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
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
1067
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
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
1088
1089
1090 static boolean lessThanUnsigned(long x1, long x2) {
1091 return (x1 + Long.MIN_VALUE) < (x2 + Long.MIN_VALUE);
1092 }
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105 @Override
1106 public int compareTo(byte[] buffer1, int offset1, int length1,
1107 byte[] buffer2, int offset2, int length2) {
1108
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
1121
1122
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
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
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
1173
1174
1175
1176 public static boolean equals(final byte [] left, final byte [] right) {
1177
1178
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
1185
1186
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
1195 if (left == right &&
1196 leftOffset == rightOffset &&
1197 leftLen == rightLen) {
1198 return true;
1199 }
1200
1201 if (leftLen != rightLen) {
1202 return false;
1203 }
1204 if (leftLen == 0) {
1205 return true;
1206 }
1207
1208
1209
1210
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
1220
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
1231
1232
1233
1234
1235 public static int hashCode(final byte [] b) {
1236 return hashCode(b, b.length);
1237 }
1238
1239
1240
1241
1242
1243
1244
1245
1246 public static int hashCode(final byte [] b, final int length) {
1247 return WritableComparator.hashBytes(b, length);
1248 }
1249
1250
1251
1252
1253
1254
1255 public static Integer mapKey(final byte [] b) {
1256 return hashCode(b);
1257 }
1258
1259
1260
1261
1262
1263
1264
1265 public static Integer mapKey(final byte [] b, final int length) {
1266 return hashCode(b, length);
1267 }
1268
1269
1270
1271
1272
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
1280
1281
1282
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
1294
1295
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
1308
1309
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
1322
1323
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
1335
1336
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
1348
1349
1350
1351
1352
1353
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
1361
1362
1363
1364
1365
1366
1367
1368
1369
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
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
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
1476
1477
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
1488
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
1500
1501
1502
1503 public static byte [][] toByteArrays(final String column) {
1504 return toByteArrays(toBytes(column));
1505 }
1506
1507
1508
1509
1510
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
1520
1521
1522
1523
1524
1525
1526
1527
1528
1529
1530
1531
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
1541
1542 int cmp = comparator.compare(key, offset, length,
1543 arr[mid], 0, arr[mid].length);
1544
1545 if (cmp > 0)
1546 low = mid + 1;
1547
1548 else if (cmp < 0)
1549 high = mid - 1;
1550
1551 else
1552 return mid;
1553 }
1554 return - (low+1);
1555 }
1556
1557
1558
1559
1560
1561
1562
1563
1564
1565 public static byte [] incrementBytes(byte[] value, long amount)
1566 {
1567 byte[] val = value;
1568 if (val.length < SIZEOF_LONG) {
1569
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
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
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
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
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 }