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