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 minLength = Math.min(length1, length2);
1419 final int minWords = minLength / SIZEOF_LONG;
1420 final long offset1Adj = offset1 + BYTE_ARRAY_BASE_OFFSET;
1421 final long offset2Adj = offset2 + BYTE_ARRAY_BASE_OFFSET;
1422
1423
1424
1425
1426
1427
1428
1429 int j = minWords << 3;
1430 for (int i = 0; i < j; i += SIZEOF_LONG) {
1431 long lw = theUnsafe.getLong(buffer1, offset1Adj + (long) i);
1432 long rw = theUnsafe.getLong(buffer2, offset2Adj + (long) i);
1433 long diff = lw ^ rw;
1434 if (diff != 0) {
1435 return lessThanUnsignedLong(lw, rw) ? -1 : 1;
1436 }
1437 }
1438 int offset = j;
1439
1440 if (minLength - offset >= SIZEOF_INT) {
1441 int il = theUnsafe.getInt(buffer1, offset1Adj + offset);
1442 int ir = theUnsafe.getInt(buffer2, offset2Adj + offset);
1443 if (il != ir) {
1444 return lessThanUnsignedInt(il, ir) ? -1: 1;
1445 }
1446 offset += SIZEOF_INT;
1447 }
1448 if (minLength - offset >= SIZEOF_SHORT) {
1449 short sl = theUnsafe.getShort(buffer1, offset1Adj + offset);
1450 short sr = theUnsafe.getShort(buffer2, offset2Adj + offset);
1451 if (sl != sr) {
1452 return lessThanUnsignedShort(sl, sr) ? -1: 1;
1453 }
1454 offset += SIZEOF_SHORT;
1455 }
1456 if (minLength - offset == 1) {
1457 int a = (buffer1[(int)(offset1 + offset)] & 0xff);
1458 int b = (buffer2[(int)(offset2 + offset)] & 0xff);
1459 if (a != b) {
1460 return a - b;
1461 }
1462 }
1463 return length1 - length2;
1464 }
1465 }
1466 }
1467
1468
1469
1470
1471
1472
1473 public static boolean equals(final byte [] left, final byte [] right) {
1474
1475
1476 if (left == right) return true;
1477 if (left == null || right == null) return false;
1478 if (left.length != right.length) return false;
1479 if (left.length == 0) return true;
1480
1481
1482
1483
1484 if (left[left.length - 1] != right[right.length - 1]) return false;
1485
1486 return compareTo(left, right) == 0;
1487 }
1488
1489 public static boolean equals(final byte[] left, int leftOffset, int leftLen,
1490 final byte[] right, int rightOffset, int rightLen) {
1491
1492 if (left == right &&
1493 leftOffset == rightOffset &&
1494 leftLen == rightLen) {
1495 return true;
1496 }
1497
1498 if (leftLen != rightLen) {
1499 return false;
1500 }
1501 if (leftLen == 0) {
1502 return true;
1503 }
1504
1505
1506
1507
1508 if (left[leftOffset + leftLen - 1] != right[rightOffset + rightLen - 1]) return false;
1509
1510 return LexicographicalComparerHolder.BEST_COMPARER.
1511 compareTo(left, leftOffset, leftLen, right, rightOffset, rightLen) == 0;
1512 }
1513
1514
1515
1516
1517
1518
1519
1520 public static boolean equals(byte[] a, ByteBuffer buf) {
1521 if (a == null) return buf == null;
1522 if (buf == null) return false;
1523 if (a.length != buf.remaining()) return false;
1524
1525
1526 ByteBuffer b = buf.duplicate();
1527 for (byte anA : a) {
1528 if (anA != b.get()) {
1529 return false;
1530 }
1531 }
1532 return true;
1533 }
1534
1535
1536
1537
1538
1539
1540 public static boolean startsWith(byte[] bytes, byte[] prefix) {
1541 return bytes != null && prefix != null &&
1542 bytes.length >= prefix.length &&
1543 LexicographicalComparerHolder.BEST_COMPARER.
1544 compareTo(bytes, 0, prefix.length, prefix, 0, prefix.length) == 0;
1545 }
1546
1547
1548
1549
1550
1551
1552
1553 public static int hashCode(final byte [] b) {
1554 return hashCode(b, b.length);
1555 }
1556
1557
1558
1559
1560
1561
1562
1563
1564 public static int hashCode(final byte [] b, final int length) {
1565 return WritableComparator.hashBytes(b, length);
1566 }
1567
1568
1569
1570
1571
1572
1573 public static Integer mapKey(final byte [] b) {
1574 return hashCode(b);
1575 }
1576
1577
1578
1579
1580
1581
1582
1583 public static Integer mapKey(final byte [] b, final int length) {
1584 return hashCode(b, length);
1585 }
1586
1587
1588
1589
1590
1591
1592 public static byte [] add(final byte [] a, final byte [] b) {
1593 return add(a, b, EMPTY_BYTE_ARRAY);
1594 }
1595
1596
1597
1598
1599
1600
1601
1602 public static byte [] add(final byte [] a, final byte [] b, final byte [] c) {
1603 byte [] result = new byte[a.length + b.length + c.length];
1604 System.arraycopy(a, 0, result, 0, a.length);
1605 System.arraycopy(b, 0, result, a.length, b.length);
1606 System.arraycopy(c, 0, result, a.length + b.length, c.length);
1607 return result;
1608 }
1609
1610
1611
1612
1613
1614 public static byte [] add(final byte [][] arrays) {
1615 int length = 0;
1616 for (int i = 0; i < arrays.length; i++) {
1617 length += arrays[i].length;
1618 }
1619 byte [] result = new byte[length];
1620 int index = 0;
1621 for (int i = 0; i < arrays.length; i++) {
1622 System.arraycopy(arrays[i], 0, result, index, arrays[i].length);
1623 index += arrays[i].length;
1624 }
1625 return result;
1626 }
1627
1628
1629
1630
1631
1632
1633 public static byte [] head(final byte [] a, final int length) {
1634 if (a.length < length) {
1635 return null;
1636 }
1637 byte [] result = new byte[length];
1638 System.arraycopy(a, 0, result, 0, length);
1639 return result;
1640 }
1641
1642
1643
1644
1645
1646
1647 public static byte [] tail(final byte [] a, final int length) {
1648 if (a.length < length) {
1649 return null;
1650 }
1651 byte [] result = new byte[length];
1652 System.arraycopy(a, a.length - length, result, 0, length);
1653 return result;
1654 }
1655
1656
1657
1658
1659
1660
1661 public static byte [] padHead(final byte [] a, final int length) {
1662 byte [] padding = new byte[length];
1663 for (int i = 0; i < length; i++) {
1664 padding[i] = 0;
1665 }
1666 return add(padding,a);
1667 }
1668
1669
1670
1671
1672
1673
1674 public static byte [] padTail(final byte [] a, final int length) {
1675 byte [] padding = new byte[length];
1676 for (int i = 0; i < length; i++) {
1677 padding[i] = 0;
1678 }
1679 return add(a,padding);
1680 }
1681
1682
1683
1684
1685
1686
1687
1688
1689
1690
1691 public static byte [][] split(final byte [] a, final byte [] b, final int num) {
1692 return split(a, b, false, num);
1693 }
1694
1695
1696
1697
1698
1699
1700
1701
1702
1703
1704
1705
1706
1707 public static byte[][] split(final byte[] a, final byte[] b,
1708 boolean inclusive, final int num) {
1709 byte[][] ret = new byte[num + 2][];
1710 int i = 0;
1711 Iterable<byte[]> iter = iterateOnSplits(a, b, inclusive, num);
1712 if (iter == null)
1713 return null;
1714 for (byte[] elem : iter) {
1715 ret[i++] = elem;
1716 }
1717 return ret;
1718 }
1719
1720
1721
1722
1723 public static Iterable<byte[]> iterateOnSplits(final byte[] a,
1724 final byte[] b, final int num)
1725 {
1726 return iterateOnSplits(a, b, false, num);
1727 }
1728
1729
1730
1731
1732 public static Iterable<byte[]> iterateOnSplits(
1733 final byte[] a, final byte[]b, boolean inclusive, final int num)
1734 {
1735 byte [] aPadded;
1736 byte [] bPadded;
1737 if (a.length < b.length) {
1738 aPadded = padTail(a, b.length - a.length);
1739 bPadded = b;
1740 } else if (b.length < a.length) {
1741 aPadded = a;
1742 bPadded = padTail(b, a.length - b.length);
1743 } else {
1744 aPadded = a;
1745 bPadded = b;
1746 }
1747 if (compareTo(aPadded,bPadded) >= 0) {
1748 throw new IllegalArgumentException("b <= a");
1749 }
1750 if (num <= 0) {
1751 throw new IllegalArgumentException("num cannot be <= 0");
1752 }
1753 byte [] prependHeader = {1, 0};
1754 final BigInteger startBI = new BigInteger(add(prependHeader, aPadded));
1755 final BigInteger stopBI = new BigInteger(add(prependHeader, bPadded));
1756 BigInteger diffBI = stopBI.subtract(startBI);
1757 if (inclusive) {
1758 diffBI = diffBI.add(BigInteger.ONE);
1759 }
1760 final BigInteger splitsBI = BigInteger.valueOf(num + 1);
1761
1762 if(diffBI.compareTo(splitsBI) < 0) {
1763 byte[] aPaddedAdditional = new byte[aPadded.length+1];
1764 byte[] bPaddedAdditional = new byte[bPadded.length+1];
1765 for (int i = 0; i < aPadded.length; i++){
1766 aPaddedAdditional[i] = aPadded[i];
1767 }
1768 for (int j = 0; j < bPadded.length; j++){
1769 bPaddedAdditional[j] = bPadded[j];
1770 }
1771 aPaddedAdditional[aPadded.length] = 0;
1772 bPaddedAdditional[bPadded.length] = 0;
1773 return iterateOnSplits(aPaddedAdditional, bPaddedAdditional, inclusive, num);
1774 }
1775 final BigInteger intervalBI;
1776 try {
1777 intervalBI = diffBI.divide(splitsBI);
1778 } catch(Exception e) {
1779 LOG.error("Exception caught during division", e);
1780 return null;
1781 }
1782
1783 final Iterator<byte[]> iterator = new Iterator<byte[]>() {
1784 private int i = -1;
1785
1786 @Override
1787 public boolean hasNext() {
1788 return i < num+1;
1789 }
1790
1791 @Override
1792 public byte[] next() {
1793 i++;
1794 if (i == 0) return a;
1795 if (i == num + 1) return b;
1796
1797 BigInteger curBI = startBI.add(intervalBI.multiply(BigInteger.valueOf(i)));
1798 byte [] padded = curBI.toByteArray();
1799 if (padded[1] == 0)
1800 padded = tail(padded, padded.length - 2);
1801 else
1802 padded = tail(padded, padded.length - 1);
1803 return padded;
1804 }
1805
1806 @Override
1807 public void remove() {
1808 throw new UnsupportedOperationException();
1809 }
1810
1811 };
1812
1813 return new Iterable<byte[]>() {
1814 @Override
1815 public Iterator<byte[]> iterator() {
1816 return iterator;
1817 }
1818 };
1819 }
1820
1821
1822
1823
1824
1825
1826 public static int hashCode(byte[] bytes, int offset, int length) {
1827 int hash = 1;
1828 for (int i = offset; i < offset + length; i++)
1829 hash = (31 * hash) + (int) bytes[i];
1830 return hash;
1831 }
1832
1833
1834
1835
1836
1837 public static byte [][] toByteArrays(final String [] t) {
1838 byte [][] result = new byte[t.length][];
1839 for (int i = 0; i < t.length; i++) {
1840 result[i] = Bytes.toBytes(t[i]);
1841 }
1842 return result;
1843 }
1844
1845
1846
1847
1848
1849 public static byte[][] toBinaryByteArrays(final String[] t) {
1850 byte[][] result = new byte[t.length][];
1851 for (int i = 0; i < t.length; i++) {
1852 result[i] = Bytes.toBytesBinary(t[i]);
1853 }
1854 return result;
1855 }
1856
1857
1858
1859
1860
1861
1862 public static byte [][] toByteArrays(final String column) {
1863 return toByteArrays(toBytes(column));
1864 }
1865
1866
1867
1868
1869
1870
1871 public static byte [][] toByteArrays(final byte [] column) {
1872 byte [][] result = new byte[1][];
1873 result[0] = column;
1874 return result;
1875 }
1876
1877
1878
1879
1880
1881
1882
1883
1884
1885
1886
1887
1888
1889
1890
1891
1892 public static int binarySearch(byte [][]arr, byte []key, int offset,
1893 int length, RawComparator<?> comparator) {
1894 int low = 0;
1895 int high = arr.length - 1;
1896
1897 while (low <= high) {
1898 int mid = (low+high) >>> 1;
1899
1900
1901 int cmp = comparator.compare(key, offset, length,
1902 arr[mid], 0, arr[mid].length);
1903
1904 if (cmp > 0)
1905 low = mid + 1;
1906
1907 else if (cmp < 0)
1908 high = mid - 1;
1909
1910 else
1911 return mid;
1912 }
1913 return - (low+1);
1914 }
1915
1916
1917
1918
1919
1920
1921
1922
1923
1924
1925
1926
1927
1928
1929
1930 public static int binarySearch(byte[][] arr, Cell key, RawComparator<Cell> comparator) {
1931 int low = 0;
1932 int high = arr.length - 1;
1933 KeyValue.KeyOnlyKeyValue r = new KeyValue.KeyOnlyKeyValue();
1934 while (low <= high) {
1935 int mid = (low+high) >>> 1;
1936
1937
1938 r.setKey(arr[mid], 0, arr[mid].length);
1939 int cmp = comparator.compare(key, r);
1940
1941 if (cmp > 0)
1942 low = mid + 1;
1943
1944 else if (cmp < 0)
1945 high = mid - 1;
1946
1947 else
1948 return mid;
1949 }
1950 return - (low+1);
1951 }
1952
1953
1954
1955
1956
1957
1958
1959
1960
1961 public static byte [] incrementBytes(byte[] value, long amount)
1962 {
1963 byte[] val = value;
1964 if (val.length < SIZEOF_LONG) {
1965
1966 byte [] newvalue;
1967 if (val[0] < 0) {
1968 newvalue = new byte[]{-1, -1, -1, -1, -1, -1, -1, -1};
1969 } else {
1970 newvalue = new byte[SIZEOF_LONG];
1971 }
1972 System.arraycopy(val, 0, newvalue, newvalue.length - val.length,
1973 val.length);
1974 val = newvalue;
1975 } else if (val.length > SIZEOF_LONG) {
1976 throw new IllegalArgumentException("Increment Bytes - value too big: " +
1977 val.length);
1978 }
1979 if(amount == 0) return val;
1980 if(val[0] < 0){
1981 return binaryIncrementNeg(val, amount);
1982 }
1983 return binaryIncrementPos(val, amount);
1984 }
1985
1986
1987 private static byte [] binaryIncrementPos(byte [] value, long amount) {
1988 long amo = amount;
1989 int sign = 1;
1990 if (amount < 0) {
1991 amo = -amount;
1992 sign = -1;
1993 }
1994 for(int i=0;i<value.length;i++) {
1995 int cur = ((int)amo % 256) * sign;
1996 amo = (amo >> 8);
1997 int val = value[value.length-i-1] & 0x0ff;
1998 int total = val + cur;
1999 if(total > 255) {
2000 amo += sign;
2001 total %= 256;
2002 } else if (total < 0) {
2003 amo -= sign;
2004 }
2005 value[value.length-i-1] = (byte)total;
2006 if (amo == 0) return value;
2007 }
2008 return value;
2009 }
2010
2011
2012 private static byte [] binaryIncrementNeg(byte [] value, long amount) {
2013 long amo = amount;
2014 int sign = 1;
2015 if (amount < 0) {
2016 amo = -amount;
2017 sign = -1;
2018 }
2019 for(int i=0;i<value.length;i++) {
2020 int cur = ((int)amo % 256) * sign;
2021 amo = (amo >> 8);
2022 int val = ((~value[value.length-i-1]) & 0x0ff) + 1;
2023 int total = cur - val;
2024 if(total >= 0) {
2025 amo += sign;
2026 } else if (total < -256) {
2027 amo -= sign;
2028 total %= 256;
2029 }
2030 value[value.length-i-1] = (byte)total;
2031 if (amo == 0) return value;
2032 }
2033 return value;
2034 }
2035
2036
2037
2038
2039 public static void writeStringFixedSize(final DataOutput out, String s,
2040 int size) throws IOException {
2041 byte[] b = toBytes(s);
2042 if (b.length > size) {
2043 throw new IOException("Trying to write " + b.length + " bytes (" +
2044 toStringBinary(b) + ") into a field of length " + size);
2045 }
2046
2047 out.writeBytes(s);
2048 for (int i = 0; i < size - s.length(); ++i)
2049 out.writeByte(0);
2050 }
2051
2052
2053
2054
2055 public static String readStringFixedSize(final DataInput in, int size)
2056 throws IOException {
2057 byte[] b = new byte[size];
2058 in.readFully(b);
2059 int n = b.length;
2060 while (n > 0 && b[n - 1] == 0)
2061 --n;
2062
2063 return toString(b, 0, n);
2064 }
2065
2066
2067
2068
2069
2070
2071
2072 public static byte [] copy(byte [] bytes) {
2073 if (bytes == null) return null;
2074 byte [] result = new byte[bytes.length];
2075 System.arraycopy(bytes, 0, result, 0, bytes.length);
2076 return result;
2077 }
2078
2079
2080
2081
2082
2083
2084
2085
2086
2087 public static byte [] copy(byte [] bytes, final int offset, final int length) {
2088 if (bytes == null) return null;
2089 byte [] result = new byte[length];
2090 System.arraycopy(bytes, offset, result, 0, length);
2091 return result;
2092 }
2093
2094
2095
2096
2097
2098
2099
2100
2101
2102
2103
2104 public static int unsignedBinarySearch(byte[] a, int fromIndex, int toIndex, byte key) {
2105 int unsignedKey = key & 0xff;
2106 int low = fromIndex;
2107 int high = toIndex - 1;
2108
2109 while (low <= high) {
2110 int mid = (low + high) >>> 1;
2111 int midVal = a[mid] & 0xff;
2112
2113 if (midVal < unsignedKey) {
2114 low = mid + 1;
2115 } else if (midVal > unsignedKey) {
2116 high = mid - 1;
2117 } else {
2118 return mid;
2119 }
2120 }
2121 return -(low + 1);
2122 }
2123
2124
2125
2126
2127
2128
2129
2130
2131 public static byte[] unsignedCopyAndIncrement(final byte[] input) {
2132 byte[] copy = copy(input);
2133 if (copy == null) {
2134 throw new IllegalArgumentException("cannot increment null array");
2135 }
2136 for (int i = copy.length - 1; i >= 0; --i) {
2137 if (copy[i] == -1) {
2138 copy[i] = 0;
2139 } else {
2140 ++copy[i];
2141 return copy;
2142 }
2143 }
2144
2145 byte[] out = new byte[copy.length + 1];
2146 out[0] = 1;
2147 System.arraycopy(copy, 0, out, 1, copy.length);
2148 return out;
2149 }
2150
2151 public static boolean equals(List<byte[]> a, List<byte[]> b) {
2152 if (a == null) {
2153 if (b == null) {
2154 return true;
2155 }
2156 return false;
2157 }
2158 if (b == null) {
2159 return false;
2160 }
2161 if (a.size() != b.size()) {
2162 return false;
2163 }
2164 for (int i = 0; i < a.size(); ++i) {
2165 if (!Bytes.equals(a.get(i), b.get(i))) {
2166 return false;
2167 }
2168 }
2169 return true;
2170 }
2171
2172 public static boolean isSorted(Collection<byte[]> arrays) {
2173 byte[] previous = new byte[0];
2174 for (byte[] array : IterableUtils.nullSafe(arrays)) {
2175 if (Bytes.compareTo(previous, array) > 0) {
2176 return false;
2177 }
2178 previous = array;
2179 }
2180 return true;
2181 }
2182
2183 public static List<byte[]> getUtf8ByteArrays(List<String> strings) {
2184 List<byte[]> byteArrays = Lists.newArrayListWithCapacity(CollectionUtils.nullSafeSize(strings));
2185 for (String s : IterableUtils.nullSafe(strings)) {
2186 byteArrays.add(Bytes.toBytes(s));
2187 }
2188 return byteArrays;
2189 }
2190
2191
2192
2193
2194
2195
2196
2197
2198
2199
2200 public static int indexOf(byte[] array, byte target) {
2201 for (int i = 0; i < array.length; i++) {
2202 if (array[i] == target) {
2203 return i;
2204 }
2205 }
2206 return -1;
2207 }
2208
2209
2210
2211
2212
2213
2214
2215
2216
2217
2218
2219
2220 public static int indexOf(byte[] array, byte[] target) {
2221 checkNotNull(array, "array");
2222 checkNotNull(target, "target");
2223 if (target.length == 0) {
2224 return 0;
2225 }
2226
2227 outer:
2228 for (int i = 0; i < array.length - target.length + 1; i++) {
2229 for (int j = 0; j < target.length; j++) {
2230 if (array[i + j] != target[j]) {
2231 continue outer;
2232 }
2233 }
2234 return i;
2235 }
2236 return -1;
2237 }
2238
2239
2240
2241
2242
2243
2244 public static boolean contains(byte[] array, byte target) {
2245 return indexOf(array, target) > -1;
2246 }
2247
2248
2249
2250
2251
2252
2253 public static boolean contains(byte[] array, byte[] target) {
2254 return indexOf(array, target) > -1;
2255 }
2256
2257
2258
2259
2260
2261 public static void zero(byte[] b) {
2262 zero(b, 0, b.length);
2263 }
2264
2265
2266
2267
2268
2269
2270
2271 public static void zero(byte[] b, int offset, int length) {
2272 checkPositionIndex(offset, b.length, "offset");
2273 checkArgument(length > 0, "length must be greater than 0");
2274 checkPositionIndex(offset + length, b.length, "offset + length");
2275 Arrays.fill(b, offset, offset + length, (byte) 0);
2276 }
2277
2278 private static final SecureRandom RNG = new SecureRandom();
2279
2280
2281
2282
2283
2284 public static void random(byte[] b) {
2285 RNG.nextBytes(b);
2286 }
2287
2288
2289
2290
2291
2292
2293
2294 public static void random(byte[] b, int offset, int length) {
2295 checkPositionIndex(offset, b.length, "offset");
2296 checkArgument(length > 0, "length must be greater than 0");
2297 checkPositionIndex(offset + length, b.length, "offset + length");
2298 byte[] buf = new byte[length];
2299 RNG.nextBytes(buf);
2300 System.arraycopy(buf, 0, b, offset, length);
2301 }
2302
2303
2304
2305
2306
2307
2308 public static byte[] createMaxByteArray(int maxByteCount) {
2309 byte[] maxByteArray = new byte[maxByteCount];
2310 for (int i = 0; i < maxByteArray.length; i++) {
2311 maxByteArray[i] = (byte) 0xff;
2312 }
2313 return maxByteArray;
2314 }
2315
2316
2317
2318
2319
2320
2321
2322 public static byte[] multiple(byte[] srcBytes, int multiNum) {
2323 if (multiNum <= 0) {
2324 return new byte[0];
2325 }
2326 byte[] result = new byte[srcBytes.length * multiNum];
2327 for (int i = 0; i < multiNum; i++) {
2328 System.arraycopy(srcBytes, 0, result, i * srcBytes.length,
2329 srcBytes.length);
2330 }
2331 return result;
2332 }
2333
2334 private static final char[] HEX_CHARS = {
2335 '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'
2336 };
2337
2338
2339
2340
2341 public static String toHex(byte[] b, int offset, int length) {
2342 checkArgument(length <= Integer.MAX_VALUE / 2);
2343 int numChars = length * 2;
2344 char[] ch = new char[numChars];
2345 for (int i = 0; i < numChars; i += 2)
2346 {
2347 byte d = b[offset + i/2];
2348 ch[i] = HEX_CHARS[(d >> 4) & 0x0F];
2349 ch[i+1] = HEX_CHARS[d & 0x0F];
2350 }
2351 return new String(ch);
2352 }
2353
2354
2355
2356
2357 public static String toHex(byte[] b) {
2358 return toHex(b, 0, b.length);
2359 }
2360
2361 private static int hexCharToNibble(char ch) {
2362 if (ch <= '9' && ch >= '0') {
2363 return ch - '0';
2364 } else if (ch >= 'a' && ch <= 'f') {
2365 return ch - 'a' + 10;
2366 } else if (ch >= 'A' && ch <= 'F') {
2367 return ch - 'A' + 10;
2368 }
2369 throw new IllegalArgumentException("Invalid hex char: " + ch);
2370 }
2371
2372 private static byte hexCharsToByte(char c1, char c2) {
2373 return (byte) ((hexCharToNibble(c1) << 4) | hexCharToNibble(c2));
2374 }
2375
2376
2377
2378
2379
2380
2381 public static byte[] fromHex(String hex) {
2382 checkArgument(hex.length() % 2 == 0, "length must be a multiple of 2");
2383 int len = hex.length();
2384 byte[] b = new byte[len / 2];
2385 for (int i = 0; i < len; i += 2) {
2386 b[i / 2] = hexCharsToByte(hex.charAt(i),hex.charAt(i+1));
2387 }
2388 return b;
2389 }
2390
2391 }