1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18 package org.apache.hadoop.hbase.util;
19
20 import static com.google.common.base.Preconditions.checkArgument;
21 import static com.google.common.base.Preconditions.checkNotNull;
22 import static com.google.common.base.Preconditions.checkPositionIndex;
23
24 import java.io.DataInput;
25 import java.io.DataOutput;
26 import java.io.IOException;
27 import java.math.BigDecimal;
28 import java.math.BigInteger;
29 import java.nio.ByteBuffer;
30 import java.nio.ByteOrder;
31 import java.nio.charset.Charset;
32 import java.security.SecureRandom;
33 import java.util.Arrays;
34 import java.util.Collection;
35 import java.util.Comparator;
36 import java.util.Iterator;
37 import java.util.List;
38
39 import org.apache.commons.logging.Log;
40 import org.apache.commons.logging.LogFactory;
41 import org.apache.hadoop.hbase.classification.InterfaceAudience;
42 import org.apache.hadoop.hbase.classification.InterfaceStability;
43 import org.apache.hadoop.hbase.Cell;
44 import org.apache.hadoop.hbase.KeyValue;
45 import org.apache.hadoop.io.RawComparator;
46 import org.apache.hadoop.io.WritableComparator;
47 import org.apache.hadoop.io.WritableUtils;
48
49 import sun.misc.Unsafe;
50
51 import com.google.common.annotations.VisibleForTesting;
52 import com.google.common.collect.Lists;
53
54 import org.apache.hadoop.hbase.util.Bytes.LexicographicalComparerHolder.UnsafeComparer;
55
56
57
58
59
60
61 @SuppressWarnings("restriction")
62 @InterfaceAudience.Public
63 @InterfaceStability.Stable
64 public class Bytes {
65
66
67 private static final String UTF8_ENCODING = "UTF-8";
68
69
70
71 private static final Charset UTF8_CHARSET = Charset.forName(UTF8_ENCODING);
72
73
74 private static final byte [] EMPTY_BYTE_ARRAY = new byte [0];
75
76 private static final Log LOG = LogFactory.getLog(Bytes.class);
77
78
79
80
81 public static final int SIZEOF_BOOLEAN = Byte.SIZE / Byte.SIZE;
82
83
84
85
86 public static final int SIZEOF_BYTE = SIZEOF_BOOLEAN;
87
88
89
90
91 public static final int SIZEOF_CHAR = Character.SIZE / Byte.SIZE;
92
93
94
95
96 public static final int SIZEOF_DOUBLE = Double.SIZE / Byte.SIZE;
97
98
99
100
101 public static final int SIZEOF_FLOAT = Float.SIZE / Byte.SIZE;
102
103
104
105
106 public static final int SIZEOF_INT = Integer.SIZE / Byte.SIZE;
107
108
109
110
111 public static final int SIZEOF_LONG = Long.SIZE / Byte.SIZE;
112
113
114
115
116 public static final int SIZEOF_SHORT = Short.SIZE / Byte.SIZE;
117
118
119
120
121
122 public static final long MASK_FOR_LOWER_INT_IN_LONG = 0xFFFFFFFF00000000l;
123
124
125
126
127
128
129
130 public static final int ESTIMATED_HEAP_TAX = 16;
131
132 private static final boolean UNSAFE_UNALIGNED = UnsafeAvailChecker.unaligned();
133
134
135
136
137
138
139
140 final public static int len(byte[] b) {
141 return b == null ? 0 : b.length;
142 }
143
144
145
146
147 @InterfaceAudience.Public
148 @InterfaceStability.Stable
149 public static class ByteArrayComparator implements RawComparator<byte []> {
150
151
152
153 public ByteArrayComparator() {
154 super();
155 }
156 @Override
157 public int compare(byte [] left, byte [] right) {
158 return compareTo(left, right);
159 }
160 @Override
161 public int compare(byte [] b1, int s1, int l1, byte [] b2, int s2, int l2) {
162 return LexicographicalComparerHolder.BEST_COMPARER.
163 compareTo(b1, s1, l1, b2, s2, l2);
164 }
165 }
166
167
168
169
170
171
172
173
174
175 @InterfaceAudience.Public
176 @InterfaceStability.Stable
177 public static class RowEndKeyComparator extends ByteArrayComparator {
178 @Override
179 public int compare(byte[] left, byte[] right) {
180 return compare(left, 0, left.length, right, 0, right.length);
181 }
182 @Override
183 public int compare(byte[] b1, int s1, int l1, byte[] b2, int s2, int l2) {
184 if (b1 == b2 && s1 == s2 && l1 == l2) {
185 return 0;
186 }
187 if (l1 == 0) {
188 return l2;
189 }
190 if (l2 == 0) {
191 return -1;
192 }
193 return super.compare(b1, s1, l1, b2, s2, l2);
194 }
195 }
196
197
198
199
200 public final static Comparator<byte []> BYTES_COMPARATOR = new ByteArrayComparator();
201
202
203
204
205 public final static RawComparator<byte []> BYTES_RAWCOMPARATOR = new ByteArrayComparator();
206
207
208
209
210
211
212
213 public static byte [] readByteArray(final DataInput in)
214 throws IOException {
215 int len = WritableUtils.readVInt(in);
216 if (len < 0) {
217 throw new NegativeArraySizeException(Integer.toString(len));
218 }
219 byte [] result = new byte[len];
220 in.readFully(result, 0, len);
221 return result;
222 }
223
224
225
226
227
228
229
230 public static byte [] readByteArrayThrowsRuntime(final DataInput in) {
231 try {
232 return readByteArray(in);
233 } catch (Exception e) {
234 throw new RuntimeException(e);
235 }
236 }
237
238
239
240
241
242
243
244 public static void writeByteArray(final DataOutput out, final byte [] b)
245 throws IOException {
246 if(b == null) {
247 WritableUtils.writeVInt(out, 0);
248 } else {
249 writeByteArray(out, b, 0, b.length);
250 }
251 }
252
253
254
255
256
257
258
259
260
261 public static void writeByteArray(final DataOutput out, final byte [] b,
262 final int offset, final int length)
263 throws IOException {
264 WritableUtils.writeVInt(out, length);
265 out.write(b, offset, length);
266 }
267
268
269
270
271
272
273
274
275
276
277 public static int writeByteArray(final byte [] tgt, final int tgtOffset,
278 final byte [] src, final int srcOffset, final int srcLength) {
279 byte [] vint = vintToBytes(srcLength);
280 System.arraycopy(vint, 0, tgt, tgtOffset, vint.length);
281 int offset = tgtOffset + vint.length;
282 System.arraycopy(src, srcOffset, tgt, offset, srcLength);
283 return offset + srcLength;
284 }
285
286
287
288
289
290
291
292
293
294
295 public static int putBytes(byte[] tgtBytes, int tgtOffset, byte[] srcBytes,
296 int srcOffset, int srcLength) {
297 System.arraycopy(srcBytes, srcOffset, tgtBytes, tgtOffset, srcLength);
298 return tgtOffset + srcLength;
299 }
300
301
302
303
304
305
306
307
308 public static int putByte(byte[] bytes, int offset, byte b) {
309 bytes[offset] = b;
310 return offset + 1;
311 }
312
313
314
315
316
317
318
319
320 public static int putByteBuffer(byte[] bytes, int offset, ByteBuffer buf) {
321 int len = buf.remaining();
322 buf.get(bytes, offset, len);
323 return offset + len;
324 }
325
326
327
328
329
330
331
332
333
334
335
336 public static byte[] toBytes(ByteBuffer buf) {
337 ByteBuffer dup = buf.duplicate();
338 dup.position(0);
339 return readBytes(dup);
340 }
341
342 private static byte[] readBytes(ByteBuffer buf) {
343 byte [] result = new byte[buf.remaining()];
344 buf.get(result);
345 return result;
346 }
347
348
349
350
351
352 public static String toString(final byte [] b) {
353 if (b == null) {
354 return null;
355 }
356 return toString(b, 0, b.length);
357 }
358
359
360
361
362
363
364
365 public static String toString(final byte [] b1,
366 String sep,
367 final byte [] b2) {
368 return toString(b1, 0, b1.length) + sep + toString(b2, 0, b2.length);
369 }
370
371
372
373
374
375
376
377
378 public static String toString(final byte[] b, int off) {
379 if (b == null) {
380 return null;
381 }
382 int len = b.length - off;
383 if (len <= 0) {
384 return "";
385 }
386 return new String(b, off, len, UTF8_CHARSET);
387 }
388
389
390
391
392
393
394
395
396
397
398 public static String toString(final byte [] b, int off, int len) {
399 if (b == null) {
400 return null;
401 }
402 if (len == 0) {
403 return "";
404 }
405 return new String(b, off, len, UTF8_CHARSET);
406 }
407
408
409
410
411
412
413
414
415 public static String toStringBinary(final byte [] b) {
416 if (b == null)
417 return "null";
418 return toStringBinary(b, 0, b.length);
419 }
420
421
422
423
424
425
426
427
428
429
430
431
432 public static String toStringBinary(ByteBuffer buf) {
433 if (buf == null)
434 return "null";
435 if (buf.hasArray()) {
436 return toStringBinary(buf.array(), buf.arrayOffset(), buf.limit());
437 }
438 return toStringBinary(toBytes(buf));
439 }
440
441 private static final char[] HEX_CHARS_UPPER = {
442 '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'
443 };
444
445
446
447
448
449
450
451
452
453
454
455 public static String toStringBinary(final byte [] b, int off, int len) {
456 StringBuilder result = new StringBuilder();
457
458 if (off >= b.length) return result.toString();
459 if (off + len > b.length) len = b.length - off;
460 for (int i = off; i < off + len ; ++i ) {
461 int ch = b[i] & 0xFF;
462 if (ch >= ' ' && ch <= '~' && ch != '\\') {
463 result.append((char)ch);
464 } else {
465 result.append("\\x");
466 result.append(HEX_CHARS_UPPER[ch / 0x10]);
467 result.append(HEX_CHARS_UPPER[ch % 0x10]);
468 }
469 }
470 return result.toString();
471 }
472
473 private static boolean isHexDigit(char c) {
474 return
475 (c >= 'A' && c <= 'F') ||
476 (c >= '0' && c <= '9');
477 }
478
479
480
481
482
483
484
485 public static byte toBinaryFromHex(byte ch) {
486 if ( ch >= 'A' && ch <= 'F' )
487 return (byte) ((byte)10 + (byte) (ch - 'A'));
488
489 return (byte) (ch - '0');
490 }
491
492 public static byte [] toBytesBinary(String in) {
493
494 byte [] b = new byte[in.length()];
495 int size = 0;
496 for (int i = 0; i < in.length(); ++i) {
497 char ch = in.charAt(i);
498 if (ch == '\\' && in.length() > i+1 && in.charAt(i+1) == 'x') {
499
500 char hd1 = in.charAt(i+2);
501 char hd2 = in.charAt(i+3);
502
503
504 if (!isHexDigit(hd1) ||
505 !isHexDigit(hd2)) {
506
507 continue;
508 }
509
510 byte d = (byte) ((toBinaryFromHex((byte)hd1) << 4) + toBinaryFromHex((byte)hd2));
511
512 b[size++] = d;
513 i += 3;
514 } else {
515 b[size++] = (byte) ch;
516 }
517 }
518
519 byte [] b2 = new byte[size];
520 System.arraycopy(b, 0, b2, 0, size);
521 return b2;
522 }
523
524
525
526
527
528
529 public static byte[] toBytes(String s) {
530 return s.getBytes(UTF8_CHARSET);
531 }
532
533
534
535
536
537
538
539
540 public static byte [] toBytes(final boolean b) {
541 return new byte[] { b ? (byte) -1 : (byte) 0 };
542 }
543
544
545
546
547
548
549 public static boolean toBoolean(final byte [] b) {
550 if (b.length != 1) {
551 throw new IllegalArgumentException("Array has wrong size: " + b.length);
552 }
553 return b[0] != (byte) 0;
554 }
555
556
557
558
559
560
561
562 public static byte[] toBytes(long val) {
563 byte [] b = new byte[8];
564 for (int i = 7; i > 0; i--) {
565 b[i] = (byte) val;
566 val >>>= 8;
567 }
568 b[0] = (byte) val;
569 return b;
570 }
571
572
573
574
575
576
577
578 public static long toLong(byte[] bytes) {
579 return toLong(bytes, 0, SIZEOF_LONG);
580 }
581
582
583
584
585
586
587
588
589
590 public static long toLong(byte[] bytes, int offset) {
591 return toLong(bytes, offset, SIZEOF_LONG);
592 }
593
594
595
596
597
598
599
600
601
602
603
604 public static long toLong(byte[] bytes, int offset, final int length) {
605 if (length != SIZEOF_LONG || offset + length > bytes.length) {
606 throw explainWrongLengthOrOffset(bytes, offset, length, SIZEOF_LONG);
607 }
608 if (UNSAFE_UNALIGNED) {
609 return toLongUnsafe(bytes, offset);
610 } else {
611 long l = 0;
612 for(int i = offset; i < offset + length; i++) {
613 l <<= 8;
614 l ^= bytes[i] & 0xFF;
615 }
616 return l;
617 }
618 }
619
620 private static IllegalArgumentException
621 explainWrongLengthOrOffset(final byte[] bytes,
622 final int offset,
623 final int length,
624 final int expectedLength) {
625 String reason;
626 if (length != expectedLength) {
627 reason = "Wrong length: " + length + ", expected " + expectedLength;
628 } else {
629 reason = "offset (" + offset + ") + length (" + length + ") exceed the"
630 + " capacity of the array: " + bytes.length;
631 }
632 return new IllegalArgumentException(reason);
633 }
634
635
636
637
638
639
640
641
642
643
644 public static int putLong(byte[] bytes, int offset, long val) {
645 if (bytes.length - offset < SIZEOF_LONG) {
646 throw new IllegalArgumentException("Not enough room to put a long at"
647 + " offset " + offset + " in a " + bytes.length + " byte array");
648 }
649 if (UNSAFE_UNALIGNED) {
650 return putLongUnsafe(bytes, offset, val);
651 } else {
652 for(int i = offset + 7; i > offset; i--) {
653 bytes[i] = (byte) val;
654 val >>>= 8;
655 }
656 bytes[offset] = (byte) val;
657 return offset + SIZEOF_LONG;
658 }
659 }
660
661
662
663
664
665
666
667
668 public static int putLongUnsafe(byte[] bytes, int offset, long val)
669 {
670 if (UnsafeComparer.littleEndian) {
671 val = Long.reverseBytes(val);
672 }
673 UnsafeComparer.theUnsafe.putLong(bytes, (long) offset +
674 UnsafeComparer.BYTE_ARRAY_BASE_OFFSET , val);
675 return offset + SIZEOF_LONG;
676 }
677
678
679
680
681
682
683 public static float toFloat(byte [] bytes) {
684 return toFloat(bytes, 0);
685 }
686
687
688
689
690
691
692
693 public static float toFloat(byte [] bytes, int offset) {
694 return Float.intBitsToFloat(toInt(bytes, offset, SIZEOF_INT));
695 }
696
697
698
699
700
701
702
703 public static int putFloat(byte [] bytes, int offset, float f) {
704 return putInt(bytes, offset, Float.floatToRawIntBits(f));
705 }
706
707
708
709
710
711 public static byte [] toBytes(final float f) {
712
713 return Bytes.toBytes(Float.floatToRawIntBits(f));
714 }
715
716
717
718
719
720 public static double toDouble(final byte [] bytes) {
721 return toDouble(bytes, 0);
722 }
723
724
725
726
727
728
729 public static double toDouble(final byte [] bytes, final int offset) {
730 return Double.longBitsToDouble(toLong(bytes, offset, SIZEOF_LONG));
731 }
732
733
734
735
736
737
738
739 public static int putDouble(byte [] bytes, int offset, double d) {
740 return putLong(bytes, offset, Double.doubleToLongBits(d));
741 }
742
743
744
745
746
747
748
749
750 public static byte [] toBytes(final double d) {
751
752 return Bytes.toBytes(Double.doubleToRawLongBits(d));
753 }
754
755
756
757
758
759
760
761
762 public static byte[] toBytes(int val) {
763 byte [] b = new byte[4];
764 for(int i = 3; i > 0; i--) {
765 b[i] = (byte) val;
766 val >>>= 8;
767 }
768 b[0] = (byte) val;
769 return b;
770 }
771
772
773
774
775
776
777 public static int toInt(byte[] bytes) {
778 return toInt(bytes, 0, SIZEOF_INT);
779 }
780
781
782
783
784
785
786
787 public static int toInt(byte[] bytes, int offset) {
788 return toInt(bytes, offset, SIZEOF_INT);
789 }
790
791
792
793
794
795
796
797
798
799
800 public static int toInt(byte[] bytes, int offset, final int length) {
801 if (length != SIZEOF_INT || offset + length > bytes.length) {
802 throw explainWrongLengthOrOffset(bytes, offset, length, SIZEOF_INT);
803 }
804 if (UNSAFE_UNALIGNED) {
805 return toIntUnsafe(bytes, offset);
806 } else {
807 int n = 0;
808 for(int i = offset; i < (offset + length); i++) {
809 n <<= 8;
810 n ^= bytes[i] & 0xFF;
811 }
812 return n;
813 }
814 }
815
816
817
818
819
820
821
822 public static int toIntUnsafe(byte[] bytes, int offset) {
823 if (UnsafeComparer.littleEndian) {
824 return Integer.reverseBytes(UnsafeComparer.theUnsafe.getInt(bytes,
825 (long) offset + UnsafeComparer.BYTE_ARRAY_BASE_OFFSET));
826 } else {
827 return UnsafeComparer.theUnsafe.getInt(bytes,
828 (long) offset + UnsafeComparer.BYTE_ARRAY_BASE_OFFSET);
829 }
830 }
831
832
833
834
835
836
837
838 public static short toShortUnsafe(byte[] bytes, int offset) {
839 if (UnsafeComparer.littleEndian) {
840 return Short.reverseBytes(UnsafeComparer.theUnsafe.getShort(bytes,
841 (long) offset + UnsafeComparer.BYTE_ARRAY_BASE_OFFSET));
842 } else {
843 return UnsafeComparer.theUnsafe.getShort(bytes,
844 (long) offset + UnsafeComparer.BYTE_ARRAY_BASE_OFFSET);
845 }
846 }
847
848
849
850
851
852
853
854 public static long toLongUnsafe(byte[] bytes, int offset) {
855 if (UnsafeComparer.littleEndian) {
856 return Long.reverseBytes(UnsafeComparer.theUnsafe.getLong(bytes,
857 (long) offset + UnsafeComparer.BYTE_ARRAY_BASE_OFFSET));
858 } else {
859 return UnsafeComparer.theUnsafe.getLong(bytes,
860 (long) offset + UnsafeComparer.BYTE_ARRAY_BASE_OFFSET);
861 }
862 }
863
864
865
866
867
868
869
870
871
872
873 public static int readAsInt(byte[] bytes, int offset, final int length) {
874 if (offset + length > bytes.length) {
875 throw new IllegalArgumentException("offset (" + offset + ") + length (" + length
876 + ") exceed the" + " capacity of the array: " + bytes.length);
877 }
878 int n = 0;
879 for(int i = offset; i < (offset + length); i++) {
880 n <<= 8;
881 n ^= bytes[i] & 0xFF;
882 }
883 return n;
884 }
885
886
887
888
889
890
891
892
893
894
895 public static int putInt(byte[] bytes, int offset, int val) {
896 if (bytes.length - offset < SIZEOF_INT) {
897 throw new IllegalArgumentException("Not enough room to put an int at"
898 + " offset " + offset + " in a " + bytes.length + " byte array");
899 }
900 if (UNSAFE_UNALIGNED) {
901 return putIntUnsafe(bytes, offset, val);
902 } else {
903 for(int i= offset + 3; i > offset; i--) {
904 bytes[i] = (byte) val;
905 val >>>= 8;
906 }
907 bytes[offset] = (byte) val;
908 return offset + SIZEOF_INT;
909 }
910 }
911
912
913
914
915
916
917
918
919 public static int putIntUnsafe(byte[] bytes, int offset, int val)
920 {
921 if (UnsafeComparer.littleEndian) {
922 val = Integer.reverseBytes(val);
923 }
924 UnsafeComparer.theUnsafe.putInt(bytes, (long) offset +
925 UnsafeComparer.BYTE_ARRAY_BASE_OFFSET , val);
926 return offset + SIZEOF_INT;
927 }
928
929
930
931
932
933
934 public static byte[] toBytes(short val) {
935 byte[] b = new byte[SIZEOF_SHORT];
936 b[1] = (byte) val;
937 val >>= 8;
938 b[0] = (byte) val;
939 return b;
940 }
941
942
943
944
945
946
947 public static short toShort(byte[] bytes) {
948 return toShort(bytes, 0, SIZEOF_SHORT);
949 }
950
951
952
953
954
955
956
957 public static short toShort(byte[] bytes, int offset) {
958 return toShort(bytes, offset, SIZEOF_SHORT);
959 }
960
961
962
963
964
965
966
967
968
969
970 public static short toShort(byte[] bytes, int offset, final int length) {
971 if (length != SIZEOF_SHORT || offset + length > bytes.length) {
972 throw explainWrongLengthOrOffset(bytes, offset, length, SIZEOF_SHORT);
973 }
974 if (UNSAFE_UNALIGNED) {
975 return toShortUnsafe(bytes, offset);
976 } else {
977 short n = 0;
978 n ^= bytes[offset] & 0xFF;
979 n <<= 8;
980 n ^= bytes[offset+1] & 0xFF;
981 return n;
982 }
983 }
984
985
986
987
988
989
990
991
992
993
994 public static byte[] getBytes(ByteBuffer buf) {
995 return readBytes(buf.duplicate());
996 }
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007 public static int putShort(byte[] bytes, int offset, short val) {
1008 if (bytes.length - offset < SIZEOF_SHORT) {
1009 throw new IllegalArgumentException("Not enough room to put a short at"
1010 + " offset " + offset + " in a " + bytes.length + " byte array");
1011 }
1012 if (UNSAFE_UNALIGNED) {
1013 return putShortUnsafe(bytes, offset, val);
1014 } else {
1015 bytes[offset+1] = (byte) val;
1016 val >>= 8;
1017 bytes[offset] = (byte) val;
1018 return offset + SIZEOF_SHORT;
1019 }
1020 }
1021
1022
1023
1024
1025
1026
1027
1028
1029 public static int putShortUnsafe(byte[] bytes, int offset, short val)
1030 {
1031 if (UnsafeComparer.littleEndian) {
1032 val = Short.reverseBytes(val);
1033 }
1034 UnsafeComparer.theUnsafe.putShort(bytes, (long) offset +
1035 UnsafeComparer.BYTE_ARRAY_BASE_OFFSET , val);
1036 return offset + SIZEOF_SHORT;
1037 }
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051 public static int putAsShort(byte[] bytes, int offset, int val) {
1052 if (bytes.length - offset < SIZEOF_SHORT) {
1053 throw new IllegalArgumentException("Not enough room to put a short at"
1054 + " offset " + offset + " in a " + bytes.length + " byte array");
1055 }
1056 bytes[offset+1] = (byte) val;
1057 val >>= 8;
1058 bytes[offset] = (byte) val;
1059 return offset + SIZEOF_SHORT;
1060 }
1061
1062
1063
1064
1065
1066
1067
1068 public static byte[] toBytes(BigDecimal val) {
1069 byte[] valueBytes = val.unscaledValue().toByteArray();
1070 byte[] result = new byte[valueBytes.length + SIZEOF_INT];
1071 int offset = putInt(result, 0, val.scale());
1072 putBytes(result, offset, valueBytes, 0, valueBytes.length);
1073 return result;
1074 }
1075
1076
1077
1078
1079
1080
1081
1082
1083 public static BigDecimal toBigDecimal(byte[] bytes) {
1084 return toBigDecimal(bytes, 0, bytes.length);
1085 }
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095 public static BigDecimal toBigDecimal(byte[] bytes, int offset, final int length) {
1096 if (bytes == null || length < SIZEOF_INT + 1 ||
1097 (offset + length > bytes.length)) {
1098 return null;
1099 }
1100
1101 int scale = toInt(bytes, offset);
1102 byte[] tcBytes = new byte[length - SIZEOF_INT];
1103 System.arraycopy(bytes, offset + SIZEOF_INT, tcBytes, 0, length - SIZEOF_INT);
1104 return new BigDecimal(new BigInteger(tcBytes), scale);
1105 }
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115 public static int putBigDecimal(byte[] bytes, int offset, BigDecimal val) {
1116 if (bytes == null) {
1117 return offset;
1118 }
1119
1120 byte[] valueBytes = val.unscaledValue().toByteArray();
1121 byte[] result = new byte[valueBytes.length + SIZEOF_INT];
1122 offset = putInt(result, offset, val.scale());
1123 return putBytes(result, offset, valueBytes, 0, valueBytes.length);
1124 }
1125
1126
1127
1128
1129
1130 public static byte [] vintToBytes(final long vint) {
1131 long i = vint;
1132 int size = WritableUtils.getVIntSize(i);
1133 byte [] result = new byte[size];
1134 int offset = 0;
1135 if (i >= -112 && i <= 127) {
1136 result[offset] = (byte) i;
1137 return result;
1138 }
1139
1140 int len = -112;
1141 if (i < 0) {
1142 i ^= -1L;
1143 len = -120;
1144 }
1145
1146 long tmp = i;
1147 while (tmp != 0) {
1148 tmp = tmp >> 8;
1149 len--;
1150 }
1151
1152 result[offset++] = (byte) len;
1153
1154 len = (len < -120) ? -(len + 120) : -(len + 112);
1155
1156 for (int idx = len; idx != 0; idx--) {
1157 int shiftbits = (idx - 1) * 8;
1158 long mask = 0xFFL << shiftbits;
1159 result[offset++] = (byte)((i & mask) >> shiftbits);
1160 }
1161 return result;
1162 }
1163
1164
1165
1166
1167
1168 public static long bytesToVint(final byte [] buffer) {
1169 int offset = 0;
1170 byte firstByte = buffer[offset++];
1171 int len = WritableUtils.decodeVIntSize(firstByte);
1172 if (len == 1) {
1173 return firstByte;
1174 }
1175 long i = 0;
1176 for (int idx = 0; idx < len-1; idx++) {
1177 byte b = buffer[offset++];
1178 i = i << 8;
1179 i = i | (b & 0xFF);
1180 }
1181 return (WritableUtils.isNegativeVInt(firstByte) ? ~i : i);
1182 }
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192 @Deprecated
1193 public static long readVLong(final byte [] buffer, final int offset)
1194 throws IOException {
1195 return readAsVLong(buffer, offset);
1196 }
1197
1198
1199
1200
1201
1202
1203
1204 public static long readAsVLong(final byte [] buffer, final int offset) {
1205 byte firstByte = buffer[offset];
1206 int len = WritableUtils.decodeVIntSize(firstByte);
1207 if (len == 1) {
1208 return firstByte;
1209 }
1210 long i = 0;
1211 for (int idx = 0; idx < len-1; idx++) {
1212 byte b = buffer[offset + 1 + idx];
1213 i = i << 8;
1214 i = i | (b & 0xFF);
1215 }
1216 return (WritableUtils.isNegativeVInt(firstByte) ? ~i : i);
1217 }
1218
1219
1220
1221
1222
1223
1224 public static int compareTo(final byte [] left, final byte [] right) {
1225 return LexicographicalComparerHolder.BEST_COMPARER.
1226 compareTo(left, 0, left.length, right, 0, right.length);
1227 }
1228
1229
1230
1231
1232
1233
1234
1235
1236
1237
1238
1239
1240 public static int compareTo(byte[] buffer1, int offset1, int length1,
1241 byte[] buffer2, int offset2, int length2) {
1242 return LexicographicalComparerHolder.BEST_COMPARER.
1243 compareTo(buffer1, offset1, length1, buffer2, offset2, length2);
1244 }
1245
1246 interface Comparer<T> {
1247 int compareTo(
1248 T buffer1, int offset1, int length1, T buffer2, int offset2, int length2
1249 );
1250 }
1251
1252 @VisibleForTesting
1253 static Comparer<byte[]> lexicographicalComparerJavaImpl() {
1254 return LexicographicalComparerHolder.PureJavaComparer.INSTANCE;
1255 }
1256
1257
1258
1259
1260
1261
1262
1263
1264 @VisibleForTesting
1265 static class LexicographicalComparerHolder {
1266 static final String UNSAFE_COMPARER_NAME =
1267 LexicographicalComparerHolder.class.getName() + "$UnsafeComparer";
1268
1269 static final Comparer<byte[]> BEST_COMPARER = getBestComparer();
1270
1271
1272
1273
1274 static Comparer<byte[]> getBestComparer() {
1275 try {
1276 Class<?> theClass = Class.forName(UNSAFE_COMPARER_NAME);
1277
1278
1279 @SuppressWarnings("unchecked")
1280 Comparer<byte[]> comparer =
1281 (Comparer<byte[]>) theClass.getEnumConstants()[0];
1282 return comparer;
1283 } catch (Throwable t) {
1284 return lexicographicalComparerJavaImpl();
1285 }
1286 }
1287
1288 enum PureJavaComparer implements Comparer<byte[]> {
1289 INSTANCE;
1290
1291 @Override
1292 public int compareTo(byte[] buffer1, int offset1, int length1,
1293 byte[] buffer2, int offset2, int length2) {
1294
1295 if (buffer1 == buffer2 &&
1296 offset1 == offset2 &&
1297 length1 == length2) {
1298 return 0;
1299 }
1300
1301 int end1 = offset1 + length1;
1302 int end2 = offset2 + length2;
1303 for (int i = offset1, j = offset2; i < end1 && j < end2; i++, j++) {
1304 int a = (buffer1[i] & 0xff);
1305 int b = (buffer2[j] & 0xff);
1306 if (a != b) {
1307 return a - b;
1308 }
1309 }
1310 return length1 - length2;
1311 }
1312 }
1313
1314 @VisibleForTesting
1315 enum UnsafeComparer implements Comparer<byte[]> {
1316 INSTANCE;
1317
1318 static final Unsafe theUnsafe;
1319
1320
1321 static final int BYTE_ARRAY_BASE_OFFSET;
1322
1323 static {
1324 if (UNSAFE_UNALIGNED) {
1325 theUnsafe = UnsafeAccess.theUnsafe;
1326 } else {
1327
1328
1329 throw new Error();
1330 }
1331
1332 BYTE_ARRAY_BASE_OFFSET = theUnsafe.arrayBaseOffset(byte[].class);
1333
1334
1335 if (theUnsafe.arrayIndexScale(byte[].class) != 1) {
1336 throw new AssertionError();
1337 }
1338 }
1339
1340 static final boolean littleEndian =
1341 ByteOrder.nativeOrder().equals(ByteOrder.LITTLE_ENDIAN);
1342
1343
1344
1345
1346
1347
1348
1349
1350 static boolean lessThanUnsignedLong(long x1, long x2) {
1351 if (littleEndian) {
1352 x1 = Long.reverseBytes(x1);
1353 x2 = Long.reverseBytes(x2);
1354 }
1355 return (x1 + Long.MIN_VALUE) < (x2 + Long.MIN_VALUE);
1356 }
1357
1358
1359
1360
1361
1362
1363
1364
1365 static boolean lessThanUnsignedInt(int x1, int x2) {
1366 if (littleEndian) {
1367 x1 = Integer.reverseBytes(x1);
1368 x2 = Integer.reverseBytes(x2);
1369 }
1370 return (x1 & 0xffffffffL) < (x2 & 0xffffffffL);
1371 }
1372
1373
1374
1375
1376
1377
1378
1379
1380 static boolean lessThanUnsignedShort(short x1, short x2) {
1381 if (littleEndian) {
1382 x1 = Short.reverseBytes(x1);
1383 x2 = Short.reverseBytes(x2);
1384 }
1385 return (x1 & 0xffff) < (x2 & 0xffff);
1386 }
1387
1388
1389
1390
1391
1392 public static boolean isAvailable()
1393 {
1394 return theUnsafe != null;
1395 }
1396
1397
1398
1399
1400
1401
1402
1403
1404
1405
1406
1407
1408 @Override
1409 public int compareTo(byte[] buffer1, int offset1, int length1,
1410 byte[] buffer2, int offset2, int length2) {
1411
1412
1413 if (buffer1 == buffer2 &&
1414 offset1 == offset2 &&
1415 length1 == length2) {
1416 return 0;
1417 }
1418 final int stride = 8;
1419 final int minLength = Math.min(length1, length2);
1420 int strideLimit = minLength & ~(stride - 1);
1421 final long offset1Adj = offset1 + BYTE_ARRAY_BASE_OFFSET;
1422 final long offset2Adj = offset2 + BYTE_ARRAY_BASE_OFFSET;
1423 int i;
1424
1425
1426
1427
1428
1429 for (i = 0; i < strideLimit; i += stride) {
1430 long lw = theUnsafe.getLong(buffer1, offset1Adj + (long) i);
1431 long rw = theUnsafe.getLong(buffer2, offset2Adj + (long) i);
1432 if (lw != rw) {
1433 if (!littleEndian) {
1434 return ((lw + Long.MIN_VALUE) < (rw + Long.MIN_VALUE)) ? -1 : 1;
1435 }
1436
1437
1438
1439
1440
1441
1442
1443
1444
1445 int n = Long.numberOfTrailingZeros(lw ^ rw) & ~0x7;
1446 return ((int) ((lw >>> n) & 0xFF)) - ((int) ((rw >>> n) & 0xFF));
1447 }
1448 }
1449
1450
1451 for (; i < minLength; i++) {
1452 int a = (buffer1[offset1 + i] & 0xFF);
1453 int b = (buffer2[offset2 + i] & 0xFF);
1454 if (a != b) {
1455 return a - b;
1456 }
1457 }
1458 return length1 - length2;
1459 }
1460 }
1461 }
1462
1463
1464
1465
1466
1467
1468 public static boolean equals(final byte [] left, final byte [] right) {
1469
1470
1471 if (left == right) return true;
1472 if (left == null || right == null) return false;
1473 if (left.length != right.length) return false;
1474 if (left.length == 0) return true;
1475
1476
1477
1478
1479 if (left[left.length - 1] != right[right.length - 1]) return false;
1480
1481 return compareTo(left, right) == 0;
1482 }
1483
1484 public static boolean equals(final byte[] left, int leftOffset, int leftLen,
1485 final byte[] right, int rightOffset, int rightLen) {
1486
1487 if (left == right &&
1488 leftOffset == rightOffset &&
1489 leftLen == rightLen) {
1490 return true;
1491 }
1492
1493 if (leftLen != rightLen) {
1494 return false;
1495 }
1496 if (leftLen == 0) {
1497 return true;
1498 }
1499
1500
1501
1502
1503 if (left[leftOffset + leftLen - 1] != right[rightOffset + rightLen - 1]) return false;
1504
1505 return LexicographicalComparerHolder.BEST_COMPARER.
1506 compareTo(left, leftOffset, leftLen, right, rightOffset, rightLen) == 0;
1507 }
1508
1509
1510
1511
1512
1513
1514
1515 public static boolean equals(byte[] a, ByteBuffer buf) {
1516 if (a == null) return buf == null;
1517 if (buf == null) return false;
1518 if (a.length != buf.remaining()) return false;
1519
1520
1521 ByteBuffer b = buf.duplicate();
1522 for (byte anA : a) {
1523 if (anA != b.get()) {
1524 return false;
1525 }
1526 }
1527 return true;
1528 }
1529
1530
1531
1532
1533
1534
1535 public static boolean startsWith(byte[] bytes, byte[] prefix) {
1536 return bytes != null && prefix != null &&
1537 bytes.length >= prefix.length &&
1538 LexicographicalComparerHolder.BEST_COMPARER.
1539 compareTo(bytes, 0, prefix.length, prefix, 0, prefix.length) == 0;
1540 }
1541
1542
1543
1544
1545
1546
1547
1548 public static int hashCode(final byte [] b) {
1549 return hashCode(b, b.length);
1550 }
1551
1552
1553
1554
1555
1556
1557
1558
1559 public static int hashCode(final byte [] b, final int length) {
1560 return WritableComparator.hashBytes(b, length);
1561 }
1562
1563
1564
1565
1566
1567
1568 public static Integer mapKey(final byte [] b) {
1569 return hashCode(b);
1570 }
1571
1572
1573
1574
1575
1576
1577
1578 public static Integer mapKey(final byte [] b, final int length) {
1579 return hashCode(b, length);
1580 }
1581
1582
1583
1584
1585
1586
1587 public static byte [] add(final byte [] a, final byte [] b) {
1588 return add(a, b, EMPTY_BYTE_ARRAY);
1589 }
1590
1591
1592
1593
1594
1595
1596
1597 public static byte [] add(final byte [] a, final byte [] b, final byte [] c) {
1598 byte [] result = new byte[a.length + b.length + c.length];
1599 System.arraycopy(a, 0, result, 0, a.length);
1600 System.arraycopy(b, 0, result, a.length, b.length);
1601 System.arraycopy(c, 0, result, a.length + b.length, c.length);
1602 return result;
1603 }
1604
1605
1606
1607
1608
1609 public static byte [] add(final byte [][] arrays) {
1610 int length = 0;
1611 for (int i = 0; i < arrays.length; i++) {
1612 length += arrays[i].length;
1613 }
1614 byte [] result = new byte[length];
1615 int index = 0;
1616 for (int i = 0; i < arrays.length; i++) {
1617 System.arraycopy(arrays[i], 0, result, index, arrays[i].length);
1618 index += arrays[i].length;
1619 }
1620 return result;
1621 }
1622
1623
1624
1625
1626
1627
1628 public static byte [] head(final byte [] a, final int length) {
1629 if (a.length < length) {
1630 return null;
1631 }
1632 byte [] result = new byte[length];
1633 System.arraycopy(a, 0, result, 0, length);
1634 return result;
1635 }
1636
1637
1638
1639
1640
1641
1642 public static byte [] tail(final byte [] a, final int length) {
1643 if (a.length < length) {
1644 return null;
1645 }
1646 byte [] result = new byte[length];
1647 System.arraycopy(a, a.length - length, result, 0, length);
1648 return result;
1649 }
1650
1651
1652
1653
1654
1655
1656 public static byte [] padHead(final byte [] a, final int length) {
1657 byte [] padding = new byte[length];
1658 for (int i = 0; i < length; i++) {
1659 padding[i] = 0;
1660 }
1661 return add(padding,a);
1662 }
1663
1664
1665
1666
1667
1668
1669 public static byte [] padTail(final byte [] a, final int length) {
1670 byte [] padding = new byte[length];
1671 for (int i = 0; i < length; i++) {
1672 padding[i] = 0;
1673 }
1674 return add(a,padding);
1675 }
1676
1677
1678
1679
1680
1681
1682
1683
1684
1685
1686 public static byte [][] split(final byte [] a, final byte [] b, final int num) {
1687 return split(a, b, false, num);
1688 }
1689
1690
1691
1692
1693
1694
1695
1696
1697
1698
1699
1700
1701
1702 public static byte[][] split(final byte[] a, final byte[] b,
1703 boolean inclusive, final int num) {
1704 byte[][] ret = new byte[num + 2][];
1705 int i = 0;
1706 Iterable<byte[]> iter = iterateOnSplits(a, b, inclusive, num);
1707 if (iter == null)
1708 return null;
1709 for (byte[] elem : iter) {
1710 ret[i++] = elem;
1711 }
1712 return ret;
1713 }
1714
1715
1716
1717
1718 public static Iterable<byte[]> iterateOnSplits(final byte[] a,
1719 final byte[] b, final int num)
1720 {
1721 return iterateOnSplits(a, b, false, num);
1722 }
1723
1724
1725
1726
1727 public static Iterable<byte[]> iterateOnSplits(
1728 final byte[] a, final byte[]b, boolean inclusive, final int num)
1729 {
1730 byte [] aPadded;
1731 byte [] bPadded;
1732 if (a.length < b.length) {
1733 aPadded = padTail(a, b.length - a.length);
1734 bPadded = b;
1735 } else if (b.length < a.length) {
1736 aPadded = a;
1737 bPadded = padTail(b, a.length - b.length);
1738 } else {
1739 aPadded = a;
1740 bPadded = b;
1741 }
1742 if (compareTo(aPadded,bPadded) >= 0) {
1743 throw new IllegalArgumentException("b <= a");
1744 }
1745 if (num <= 0) {
1746 throw new IllegalArgumentException("num cannot be <= 0");
1747 }
1748 byte [] prependHeader = {1, 0};
1749 final BigInteger startBI = new BigInteger(add(prependHeader, aPadded));
1750 final BigInteger stopBI = new BigInteger(add(prependHeader, bPadded));
1751 BigInteger diffBI = stopBI.subtract(startBI);
1752 if (inclusive) {
1753 diffBI = diffBI.add(BigInteger.ONE);
1754 }
1755 final BigInteger splitsBI = BigInteger.valueOf(num + 1);
1756
1757 if(diffBI.compareTo(splitsBI) < 0) {
1758 byte[] aPaddedAdditional = new byte[aPadded.length+1];
1759 byte[] bPaddedAdditional = new byte[bPadded.length+1];
1760 for (int i = 0; i < aPadded.length; i++){
1761 aPaddedAdditional[i] = aPadded[i];
1762 }
1763 for (int j = 0; j < bPadded.length; j++){
1764 bPaddedAdditional[j] = bPadded[j];
1765 }
1766 aPaddedAdditional[aPadded.length] = 0;
1767 bPaddedAdditional[bPadded.length] = 0;
1768 return iterateOnSplits(aPaddedAdditional, bPaddedAdditional, inclusive, num);
1769 }
1770 final BigInteger intervalBI;
1771 try {
1772 intervalBI = diffBI.divide(splitsBI);
1773 } catch(Exception e) {
1774 LOG.error("Exception caught during division", e);
1775 return null;
1776 }
1777
1778 final Iterator<byte[]> iterator = new Iterator<byte[]>() {
1779 private int i = -1;
1780
1781 @Override
1782 public boolean hasNext() {
1783 return i < num+1;
1784 }
1785
1786 @Override
1787 public byte[] next() {
1788 i++;
1789 if (i == 0) return a;
1790 if (i == num + 1) return b;
1791
1792 BigInteger curBI = startBI.add(intervalBI.multiply(BigInteger.valueOf(i)));
1793 byte [] padded = curBI.toByteArray();
1794 if (padded[1] == 0)
1795 padded = tail(padded, padded.length - 2);
1796 else
1797 padded = tail(padded, padded.length - 1);
1798 return padded;
1799 }
1800
1801 @Override
1802 public void remove() {
1803 throw new UnsupportedOperationException();
1804 }
1805
1806 };
1807
1808 return new Iterable<byte[]>() {
1809 @Override
1810 public Iterator<byte[]> iterator() {
1811 return iterator;
1812 }
1813 };
1814 }
1815
1816
1817
1818
1819
1820
1821 public static int hashCode(byte[] bytes, int offset, int length) {
1822 int hash = 1;
1823 for (int i = offset; i < offset + length; i++)
1824 hash = (31 * hash) + (int) bytes[i];
1825 return hash;
1826 }
1827
1828
1829
1830
1831
1832 public static byte [][] toByteArrays(final String [] t) {
1833 byte [][] result = new byte[t.length][];
1834 for (int i = 0; i < t.length; i++) {
1835 result[i] = Bytes.toBytes(t[i]);
1836 }
1837 return result;
1838 }
1839
1840
1841
1842
1843
1844 public static byte[][] toBinaryByteArrays(final String[] t) {
1845 byte[][] result = new byte[t.length][];
1846 for (int i = 0; i < t.length; i++) {
1847 result[i] = Bytes.toBytesBinary(t[i]);
1848 }
1849 return result;
1850 }
1851
1852
1853
1854
1855
1856
1857 public static byte [][] toByteArrays(final String column) {
1858 return toByteArrays(toBytes(column));
1859 }
1860
1861
1862
1863
1864
1865
1866 public static byte [][] toByteArrays(final byte [] column) {
1867 byte [][] result = new byte[1][];
1868 result[0] = column;
1869 return result;
1870 }
1871
1872
1873
1874
1875
1876
1877
1878
1879
1880
1881
1882
1883
1884
1885
1886
1887 public static int binarySearch(byte [][]arr, byte []key, int offset,
1888 int length, RawComparator<?> comparator) {
1889 int low = 0;
1890 int high = arr.length - 1;
1891
1892 while (low <= high) {
1893 int mid = (low+high) >>> 1;
1894
1895
1896 int cmp = comparator.compare(key, offset, length,
1897 arr[mid], 0, arr[mid].length);
1898
1899 if (cmp > 0)
1900 low = mid + 1;
1901
1902 else if (cmp < 0)
1903 high = mid - 1;
1904
1905 else
1906 return mid;
1907 }
1908 return - (low+1);
1909 }
1910
1911
1912
1913
1914
1915
1916
1917
1918
1919
1920
1921
1922
1923
1924
1925 public static int binarySearch(byte[][] arr, Cell key, RawComparator<Cell> comparator) {
1926 int low = 0;
1927 int high = arr.length - 1;
1928 KeyValue.KeyOnlyKeyValue r = new KeyValue.KeyOnlyKeyValue();
1929 while (low <= high) {
1930 int mid = (low+high) >>> 1;
1931
1932
1933 r.setKey(arr[mid], 0, arr[mid].length);
1934 int cmp = comparator.compare(key, r);
1935
1936 if (cmp > 0)
1937 low = mid + 1;
1938
1939 else if (cmp < 0)
1940 high = mid - 1;
1941
1942 else
1943 return mid;
1944 }
1945 return - (low+1);
1946 }
1947
1948
1949
1950
1951
1952
1953
1954
1955
1956 public static byte [] incrementBytes(byte[] value, long amount)
1957 {
1958 byte[] val = value;
1959 if (val.length < SIZEOF_LONG) {
1960
1961 byte [] newvalue;
1962 if (val[0] < 0) {
1963 newvalue = new byte[]{-1, -1, -1, -1, -1, -1, -1, -1};
1964 } else {
1965 newvalue = new byte[SIZEOF_LONG];
1966 }
1967 System.arraycopy(val, 0, newvalue, newvalue.length - val.length,
1968 val.length);
1969 val = newvalue;
1970 } else if (val.length > SIZEOF_LONG) {
1971 throw new IllegalArgumentException("Increment Bytes - value too big: " +
1972 val.length);
1973 }
1974 if(amount == 0) return val;
1975 if(val[0] < 0){
1976 return binaryIncrementNeg(val, amount);
1977 }
1978 return binaryIncrementPos(val, amount);
1979 }
1980
1981
1982 private static byte [] binaryIncrementPos(byte [] value, long amount) {
1983 long amo = amount;
1984 int sign = 1;
1985 if (amount < 0) {
1986 amo = -amount;
1987 sign = -1;
1988 }
1989 for(int i=0;i<value.length;i++) {
1990 int cur = ((int)amo % 256) * sign;
1991 amo = (amo >> 8);
1992 int val = value[value.length-i-1] & 0x0ff;
1993 int total = val + cur;
1994 if(total > 255) {
1995 amo += sign;
1996 total %= 256;
1997 } else if (total < 0) {
1998 amo -= sign;
1999 }
2000 value[value.length-i-1] = (byte)total;
2001 if (amo == 0) return value;
2002 }
2003 return value;
2004 }
2005
2006
2007 private static byte [] binaryIncrementNeg(byte [] value, long amount) {
2008 long amo = amount;
2009 int sign = 1;
2010 if (amount < 0) {
2011 amo = -amount;
2012 sign = -1;
2013 }
2014 for(int i=0;i<value.length;i++) {
2015 int cur = ((int)amo % 256) * sign;
2016 amo = (amo >> 8);
2017 int val = ((~value[value.length-i-1]) & 0x0ff) + 1;
2018 int total = cur - val;
2019 if(total >= 0) {
2020 amo += sign;
2021 } else if (total < -256) {
2022 amo -= sign;
2023 total %= 256;
2024 }
2025 value[value.length-i-1] = (byte)total;
2026 if (amo == 0) return value;
2027 }
2028 return value;
2029 }
2030
2031
2032
2033
2034 public static void writeStringFixedSize(final DataOutput out, String s,
2035 int size) throws IOException {
2036 byte[] b = toBytes(s);
2037 if (b.length > size) {
2038 throw new IOException("Trying to write " + b.length + " bytes (" +
2039 toStringBinary(b) + ") into a field of length " + size);
2040 }
2041
2042 out.writeBytes(s);
2043 for (int i = 0; i < size - s.length(); ++i)
2044 out.writeByte(0);
2045 }
2046
2047
2048
2049
2050 public static String readStringFixedSize(final DataInput in, int size)
2051 throws IOException {
2052 byte[] b = new byte[size];
2053 in.readFully(b);
2054 int n = b.length;
2055 while (n > 0 && b[n - 1] == 0)
2056 --n;
2057
2058 return toString(b, 0, n);
2059 }
2060
2061
2062
2063
2064
2065
2066
2067 public static byte [] copy(byte [] bytes) {
2068 if (bytes == null) return null;
2069 byte [] result = new byte[bytes.length];
2070 System.arraycopy(bytes, 0, result, 0, bytes.length);
2071 return result;
2072 }
2073
2074
2075
2076
2077
2078
2079
2080
2081
2082 public static byte [] copy(byte [] bytes, final int offset, final int length) {
2083 if (bytes == null) return null;
2084 byte [] result = new byte[length];
2085 System.arraycopy(bytes, offset, result, 0, length);
2086 return result;
2087 }
2088
2089
2090
2091
2092
2093
2094
2095
2096
2097
2098
2099 public static int unsignedBinarySearch(byte[] a, int fromIndex, int toIndex, byte key) {
2100 int unsignedKey = key & 0xff;
2101 int low = fromIndex;
2102 int high = toIndex - 1;
2103
2104 while (low <= high) {
2105 int mid = (low + high) >>> 1;
2106 int midVal = a[mid] & 0xff;
2107
2108 if (midVal < unsignedKey) {
2109 low = mid + 1;
2110 } else if (midVal > unsignedKey) {
2111 high = mid - 1;
2112 } else {
2113 return mid;
2114 }
2115 }
2116 return -(low + 1);
2117 }
2118
2119
2120
2121
2122
2123
2124
2125
2126 public static byte[] unsignedCopyAndIncrement(final byte[] input) {
2127 byte[] copy = copy(input);
2128 if (copy == null) {
2129 throw new IllegalArgumentException("cannot increment null array");
2130 }
2131 for (int i = copy.length - 1; i >= 0; --i) {
2132 if (copy[i] == -1) {
2133 copy[i] = 0;
2134 } else {
2135 ++copy[i];
2136 return copy;
2137 }
2138 }
2139
2140 byte[] out = new byte[copy.length + 1];
2141 out[0] = 1;
2142 System.arraycopy(copy, 0, out, 1, copy.length);
2143 return out;
2144 }
2145
2146 public static boolean equals(List<byte[]> a, List<byte[]> b) {
2147 if (a == null) {
2148 if (b == null) {
2149 return true;
2150 }
2151 return false;
2152 }
2153 if (b == null) {
2154 return false;
2155 }
2156 if (a.size() != b.size()) {
2157 return false;
2158 }
2159 for (int i = 0; i < a.size(); ++i) {
2160 if (!Bytes.equals(a.get(i), b.get(i))) {
2161 return false;
2162 }
2163 }
2164 return true;
2165 }
2166
2167 public static boolean isSorted(Collection<byte[]> arrays) {
2168 byte[] previous = new byte[0];
2169 for (byte[] array : IterableUtils.nullSafe(arrays)) {
2170 if (Bytes.compareTo(previous, array) > 0) {
2171 return false;
2172 }
2173 previous = array;
2174 }
2175 return true;
2176 }
2177
2178 public static List<byte[]> getUtf8ByteArrays(List<String> strings) {
2179 List<byte[]> byteArrays = Lists.newArrayListWithCapacity(CollectionUtils.nullSafeSize(strings));
2180 for (String s : IterableUtils.nullSafe(strings)) {
2181 byteArrays.add(Bytes.toBytes(s));
2182 }
2183 return byteArrays;
2184 }
2185
2186
2187
2188
2189
2190
2191
2192
2193
2194
2195 public static int indexOf(byte[] array, byte target) {
2196 for (int i = 0; i < array.length; i++) {
2197 if (array[i] == target) {
2198 return i;
2199 }
2200 }
2201 return -1;
2202 }
2203
2204
2205
2206
2207
2208
2209
2210
2211
2212
2213
2214
2215 public static int indexOf(byte[] array, byte[] target) {
2216 checkNotNull(array, "array");
2217 checkNotNull(target, "target");
2218 if (target.length == 0) {
2219 return 0;
2220 }
2221
2222 outer:
2223 for (int i = 0; i < array.length - target.length + 1; i++) {
2224 for (int j = 0; j < target.length; j++) {
2225 if (array[i + j] != target[j]) {
2226 continue outer;
2227 }
2228 }
2229 return i;
2230 }
2231 return -1;
2232 }
2233
2234
2235
2236
2237
2238
2239 public static boolean contains(byte[] array, byte target) {
2240 return indexOf(array, target) > -1;
2241 }
2242
2243
2244
2245
2246
2247
2248 public static boolean contains(byte[] array, byte[] target) {
2249 return indexOf(array, target) > -1;
2250 }
2251
2252
2253
2254
2255
2256 public static void zero(byte[] b) {
2257 zero(b, 0, b.length);
2258 }
2259
2260
2261
2262
2263
2264
2265
2266 public static void zero(byte[] b, int offset, int length) {
2267 checkPositionIndex(offset, b.length, "offset");
2268 checkArgument(length > 0, "length must be greater than 0");
2269 checkPositionIndex(offset + length, b.length, "offset + length");
2270 Arrays.fill(b, offset, offset + length, (byte) 0);
2271 }
2272
2273 private static final SecureRandom RNG = new SecureRandom();
2274
2275
2276
2277
2278
2279 public static void random(byte[] b) {
2280 RNG.nextBytes(b);
2281 }
2282
2283
2284
2285
2286
2287
2288
2289 public static void random(byte[] b, int offset, int length) {
2290 checkPositionIndex(offset, b.length, "offset");
2291 checkArgument(length > 0, "length must be greater than 0");
2292 checkPositionIndex(offset + length, b.length, "offset + length");
2293 byte[] buf = new byte[length];
2294 RNG.nextBytes(buf);
2295 System.arraycopy(buf, 0, b, offset, length);
2296 }
2297
2298
2299
2300
2301
2302
2303 public static byte[] createMaxByteArray(int maxByteCount) {
2304 byte[] maxByteArray = new byte[maxByteCount];
2305 for (int i = 0; i < maxByteArray.length; i++) {
2306 maxByteArray[i] = (byte) 0xff;
2307 }
2308 return maxByteArray;
2309 }
2310
2311
2312
2313
2314
2315
2316
2317 public static byte[] multiple(byte[] srcBytes, int multiNum) {
2318 if (multiNum <= 0) {
2319 return new byte[0];
2320 }
2321 byte[] result = new byte[srcBytes.length * multiNum];
2322 for (int i = 0; i < multiNum; i++) {
2323 System.arraycopy(srcBytes, 0, result, i * srcBytes.length,
2324 srcBytes.length);
2325 }
2326 return result;
2327 }
2328
2329 private static final char[] HEX_CHARS = {
2330 '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'
2331 };
2332
2333
2334
2335
2336 public static String toHex(byte[] b, int offset, int length) {
2337 checkArgument(length <= Integer.MAX_VALUE / 2);
2338 int numChars = length * 2;
2339 char[] ch = new char[numChars];
2340 for (int i = 0; i < numChars; i += 2)
2341 {
2342 byte d = b[offset + i/2];
2343 ch[i] = HEX_CHARS[(d >> 4) & 0x0F];
2344 ch[i+1] = HEX_CHARS[d & 0x0F];
2345 }
2346 return new String(ch);
2347 }
2348
2349
2350
2351
2352 public static String toHex(byte[] b) {
2353 return toHex(b, 0, b.length);
2354 }
2355
2356 private static int hexCharToNibble(char ch) {
2357 if (ch <= '9' && ch >= '0') {
2358 return ch - '0';
2359 } else if (ch >= 'a' && ch <= 'f') {
2360 return ch - 'a' + 10;
2361 } else if (ch >= 'A' && ch <= 'F') {
2362 return ch - 'A' + 10;
2363 }
2364 throw new IllegalArgumentException("Invalid hex char: " + ch);
2365 }
2366
2367 private static byte hexCharsToByte(char c1, char c2) {
2368 return (byte) ((hexCharToNibble(c1) << 4) | hexCharToNibble(c2));
2369 }
2370
2371
2372
2373
2374
2375
2376 public static byte[] fromHex(String hex) {
2377 checkArgument(hex.length() % 2 == 0, "length must be a multiple of 2");
2378 int len = hex.length();
2379 byte[] b = new byte[len / 2];
2380 for (int i = 0; i < len; i += 2) {
2381 b[i / 2] = hexCharsToByte(hex.charAt(i),hex.charAt(i+1));
2382 }
2383 return b;
2384 }
2385
2386 }