1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20 package org.apache.hadoop.hbase.util;
21
22 import org.apache.hadoop.hbase.HConstants;
23 import org.apache.hadoop.hbase.io.ImmutableBytesWritable;
24 import org.apache.commons.logging.Log;
25 import org.apache.commons.logging.LogFactory;
26 import org.apache.hadoop.io.RawComparator;
27 import org.apache.hadoop.io.WritableComparator;
28 import org.apache.hadoop.io.WritableUtils;
29
30 import java.io.DataInput;
31 import java.io.DataOutput;
32 import java.io.IOException;
33 import java.io.UnsupportedEncodingException;
34 import java.math.BigInteger;
35 import java.nio.ByteBuffer;
36 import java.util.Comparator;
37 import java.util.Iterator;
38
39
40
41
42
43
44 public class Bytes {
45
46 private static final Log LOG = LogFactory.getLog(Bytes.class);
47
48
49
50
51 public static final int SIZEOF_BOOLEAN = Byte.SIZE / Byte.SIZE;
52
53
54
55
56 public static final int SIZEOF_BYTE = SIZEOF_BOOLEAN;
57
58
59
60
61 public static final int SIZEOF_CHAR = Character.SIZE / Byte.SIZE;
62
63
64
65
66 public static final int SIZEOF_DOUBLE = Double.SIZE / Byte.SIZE;
67
68
69
70
71 public static final int SIZEOF_FLOAT = Float.SIZE / Byte.SIZE;
72
73
74
75
76 public static final int SIZEOF_INT = Integer.SIZE / Byte.SIZE;
77
78
79
80
81 public static final int SIZEOF_LONG = Long.SIZE / Byte.SIZE;
82
83
84
85
86 public static final int SIZEOF_SHORT = Short.SIZE / Byte.SIZE;
87
88
89
90
91
92
93
94
95 public static final int ESTIMATED_HEAP_TAX = 16;
96
97
98
99
100 public static class ByteArrayComparator implements RawComparator<byte []> {
101
102
103
104 public ByteArrayComparator() {
105 super();
106 }
107 public int compare(byte [] left, byte [] right) {
108 return compareTo(left, right);
109 }
110 public int compare(byte [] b1, int s1, int l1, byte [] b2, int s2, int l2) {
111 return compareTo(b1, s1, l1, b2, s2, l2);
112 }
113 }
114
115
116
117
118 public static Comparator<byte []> BYTES_COMPARATOR =
119 new ByteArrayComparator();
120
121
122
123
124 public static RawComparator<byte []> BYTES_RAWCOMPARATOR =
125 new ByteArrayComparator();
126
127
128
129
130
131
132
133 public static byte [] readByteArray(final DataInput in)
134 throws IOException {
135 int len = WritableUtils.readVInt(in);
136 if (len < 0) {
137 throw new NegativeArraySizeException(Integer.toString(len));
138 }
139 byte [] result = new byte[len];
140 in.readFully(result, 0, len);
141 return result;
142 }
143
144
145
146
147
148
149
150 public static byte [] readByteArrayThrowsRuntime(final DataInput in) {
151 try {
152 return readByteArray(in);
153 } catch (Exception e) {
154 throw new RuntimeException(e);
155 }
156 }
157
158
159
160
161
162
163
164 public static void writeByteArray(final DataOutput out, final byte [] b)
165 throws IOException {
166 if(b == null) {
167 WritableUtils.writeVInt(out, 0);
168 } else {
169 writeByteArray(out, b, 0, b.length);
170 }
171 }
172
173
174
175
176
177
178
179
180
181 public static void writeByteArray(final DataOutput out, final byte [] b,
182 final int offset, final int length)
183 throws IOException {
184 WritableUtils.writeVInt(out, length);
185 out.write(b, offset, length);
186 }
187
188
189
190
191
192
193
194
195
196
197 public static int writeByteArray(final byte [] tgt, final int tgtOffset,
198 final byte [] src, final int srcOffset, final int srcLength) {
199 byte [] vint = vintToBytes(srcLength);
200 System.arraycopy(vint, 0, tgt, tgtOffset, vint.length);
201 int offset = tgtOffset + vint.length;
202 System.arraycopy(src, srcOffset, tgt, offset, srcLength);
203 return offset + srcLength;
204 }
205
206
207
208
209
210
211
212
213
214
215 public static int putBytes(byte[] tgtBytes, int tgtOffset, byte[] srcBytes,
216 int srcOffset, int srcLength) {
217 System.arraycopy(srcBytes, srcOffset, tgtBytes, tgtOffset, srcLength);
218 return tgtOffset + srcLength;
219 }
220
221
222
223
224
225
226
227
228 public static int putByte(byte[] bytes, int offset, byte b) {
229 bytes[offset] = b;
230 return offset + 1;
231 }
232
233
234
235
236
237
238 public static byte[] toBytes(ByteBuffer bb) {
239 int length = bb.limit();
240 byte [] result = new byte[length];
241 System.arraycopy(bb.array(), bb.arrayOffset(), result, 0, length);
242 return result;
243 }
244
245
246
247
248
249 public static String toString(final byte [] b) {
250 if (b == null) {
251 return null;
252 }
253 return toString(b, 0, b.length);
254 }
255
256
257
258
259
260
261
262 public static String toString(final byte [] b1,
263 String sep,
264 final byte [] b2) {
265 return toString(b1, 0, b1.length) + sep + toString(b2, 0, b2.length);
266 }
267
268
269
270
271
272
273
274
275
276
277
278 public static String toString(final byte [] b, int off, int len) {
279 if (b == null) {
280 return null;
281 }
282 if (len == 0) {
283 return "";
284 }
285 try {
286 return new String(b, off, len, HConstants.UTF8_ENCODING);
287 } catch (UnsupportedEncodingException e) {
288 LOG.error("UTF-8 not supported?", e);
289 return null;
290 }
291 }
292
293
294
295
296
297
298
299
300 public static String toStringBinary(final byte [] b) {
301 return toStringBinary(b, 0, b.length);
302 }
303
304
305
306
307
308
309
310
311
312
313
314 public static String toStringBinary(final byte [] b, int off, int len) {
315 StringBuilder result = new StringBuilder();
316 try {
317 String first = new String(b, off, len, "ISO-8859-1");
318 for (int i = 0; i < first.length() ; ++i ) {
319 int ch = first.charAt(i) & 0xFF;
320 if ( (ch >= '0' && ch <= '9')
321 || (ch >= 'A' && ch <= 'Z')
322 || (ch >= 'a' && ch <= 'z')
323 || " `~!@#$%^&*()-_=+[]{}\\|;:'\",.<>/?".indexOf(ch) >= 0 ) {
324 result.append(first.charAt(i));
325 } else {
326 result.append(String.format("\\x%02X", ch));
327 }
328 }
329 } catch (UnsupportedEncodingException e) {
330 LOG.error("ISO-8859-1 not supported?", e);
331 }
332 return result.toString();
333 }
334
335 private static boolean isHexDigit(char c) {
336 return
337 (c >= 'A' && c <= 'F') ||
338 (c >= '0' && c <= '9');
339 }
340
341
342
343
344
345
346
347 public static byte toBinaryFromHex(byte ch) {
348 if ( ch >= 'A' && ch <= 'F' )
349 return (byte) ((byte)10 + (byte) (ch - 'A'));
350
351 return (byte) (ch - '0');
352 }
353
354 public static byte [] toBytesBinary(String in) {
355
356 byte [] b = new byte[in.length()];
357 int size = 0;
358 for (int i = 0; i < in.length(); ++i) {
359 char ch = in.charAt(i);
360 if (ch == '\\') {
361
362 char next = in.charAt(i+1);
363 if (next != 'x') {
364
365 b[size++] = (byte)ch;
366 continue;
367 }
368
369 char hd1 = in.charAt(i+2);
370 char hd2 = in.charAt(i+3);
371
372
373 if (!isHexDigit(hd1) ||
374 !isHexDigit(hd2)) {
375
376 continue;
377 }
378
379 byte d = (byte) ((toBinaryFromHex((byte)hd1) << 4) + toBinaryFromHex((byte)hd2));
380
381 b[size++] = d;
382 i += 3;
383 } else {
384 b[size++] = (byte) ch;
385 }
386 }
387
388 byte [] b2 = new byte[size];
389 System.arraycopy(b, 0, b2, 0, size);
390 return b2;
391 }
392
393
394
395
396
397
398 public static byte[] toBytes(String s) {
399 try {
400 return s.getBytes(HConstants.UTF8_ENCODING);
401 } catch (UnsupportedEncodingException e) {
402 LOG.error("UTF-8 not supported?", e);
403 return null;
404 }
405 }
406
407
408
409
410
411
412
413
414 public static byte [] toBytes(final boolean b) {
415 return new byte[] { b ? (byte) -1 : (byte) 0 };
416 }
417
418
419
420
421
422
423 public static boolean toBoolean(final byte [] b) {
424 if (b.length != 1) {
425 throw new IllegalArgumentException("Array has wrong size: " + b.length);
426 }
427 return b[0] != (byte) 0;
428 }
429
430
431
432
433
434
435
436 public static byte[] toBytes(long val) {
437 byte [] b = new byte[8];
438 for (int i = 7; i > 0; i--) {
439 b[i] = (byte) val;
440 val >>>= 8;
441 }
442 b[0] = (byte) val;
443 return b;
444 }
445
446
447
448
449
450
451
452 public static long toLong(byte[] bytes) {
453 return toLong(bytes, 0, SIZEOF_LONG);
454 }
455
456
457
458
459
460
461
462
463
464 public static long toLong(byte[] bytes, int offset) {
465 return toLong(bytes, offset, SIZEOF_LONG);
466 }
467
468
469
470
471
472
473
474
475
476
477
478 public static long toLong(byte[] bytes, int offset, final int length) {
479 if (length != SIZEOF_LONG || offset + length > bytes.length) {
480 throw explainWrongLengthOrOffset(bytes, offset, length, SIZEOF_LONG);
481 }
482 long l = 0;
483 for(int i = offset; i < offset + length; i++) {
484 l <<= 8;
485 l ^= bytes[i] & 0xFF;
486 }
487 return l;
488 }
489
490 private static IllegalArgumentException
491 explainWrongLengthOrOffset(final byte[] bytes,
492 final int offset,
493 final int length,
494 final int expectedLength) {
495 String reason;
496 if (length != expectedLength) {
497 reason = "Wrong length: " + length + ", expected " + expectedLength;
498 } else {
499 reason = "offset (" + offset + ") + length (" + length + ") exceed the"
500 + " capacity of the array: " + bytes.length;
501 }
502 return new IllegalArgumentException(reason);
503 }
504
505
506
507
508
509
510
511
512
513
514 public static int putLong(byte[] bytes, int offset, long val) {
515 if (bytes.length - offset < SIZEOF_LONG) {
516 throw new IllegalArgumentException("Not enough room to put a long at"
517 + " offset " + offset + " in a " + bytes.length + " byte array");
518 }
519 for(int i = offset + 7; i > offset; i--) {
520 bytes[i] = (byte) val;
521 val >>>= 8;
522 }
523 bytes[offset] = (byte) val;
524 return offset + SIZEOF_LONG;
525 }
526
527
528
529
530
531
532 public static float toFloat(byte [] bytes) {
533 return toFloat(bytes, 0);
534 }
535
536
537
538
539
540
541
542 public static float toFloat(byte [] bytes, int offset) {
543 return Float.intBitsToFloat(toInt(bytes, offset, SIZEOF_INT));
544 }
545
546
547
548
549
550
551
552 public static int putFloat(byte [] bytes, int offset, float f) {
553 return putInt(bytes, offset, Float.floatToRawIntBits(f));
554 }
555
556
557
558
559
560 public static byte [] toBytes(final float f) {
561
562 return Bytes.toBytes(Float.floatToRawIntBits(f));
563 }
564
565
566
567
568
569 public static double toDouble(final byte [] bytes) {
570 return toDouble(bytes, 0);
571 }
572
573
574
575
576
577
578 public static double toDouble(final byte [] bytes, final int offset) {
579 return Double.longBitsToDouble(toLong(bytes, offset, SIZEOF_LONG));
580 }
581
582
583
584
585
586
587
588 public static int putDouble(byte [] bytes, int offset, double d) {
589 return putLong(bytes, offset, Double.doubleToLongBits(d));
590 }
591
592
593
594
595
596
597
598
599 public static byte [] toBytes(final double d) {
600
601 return Bytes.toBytes(Double.doubleToRawLongBits(d));
602 }
603
604
605
606
607
608
609 public static byte[] toBytes(int val) {
610 byte [] b = new byte[4];
611 for(int i = 3; i > 0; i--) {
612 b[i] = (byte) val;
613 val >>>= 8;
614 }
615 b[0] = (byte) val;
616 return b;
617 }
618
619
620
621
622
623
624 public static int toInt(byte[] bytes) {
625 return toInt(bytes, 0, SIZEOF_INT);
626 }
627
628
629
630
631
632
633
634 public static int toInt(byte[] bytes, int offset) {
635 return toInt(bytes, offset, SIZEOF_INT);
636 }
637
638
639
640
641
642
643
644
645
646
647 public static int toInt(byte[] bytes, int offset, final int length) {
648 if (length != SIZEOF_INT || offset + length > bytes.length) {
649 throw explainWrongLengthOrOffset(bytes, offset, length, SIZEOF_INT);
650 }
651 int n = 0;
652 for(int i = offset; i < (offset + length); i++) {
653 n <<= 8;
654 n ^= bytes[i] & 0xFF;
655 }
656 return n;
657 }
658
659
660
661
662
663
664
665
666
667
668 public static int putInt(byte[] bytes, int offset, int val) {
669 if (bytes.length - offset < SIZEOF_INT) {
670 throw new IllegalArgumentException("Not enough room to put an int at"
671 + " offset " + offset + " in a " + bytes.length + " byte array");
672 }
673 for(int i= offset + 3; i > offset; i--) {
674 bytes[i] = (byte) val;
675 val >>>= 8;
676 }
677 bytes[offset] = (byte) val;
678 return offset + SIZEOF_INT;
679 }
680
681
682
683
684
685
686 public static byte[] toBytes(short val) {
687 byte[] b = new byte[SIZEOF_SHORT];
688 b[1] = (byte) val;
689 val >>= 8;
690 b[0] = (byte) val;
691 return b;
692 }
693
694
695
696
697
698
699 public static short toShort(byte[] bytes) {
700 return toShort(bytes, 0, SIZEOF_SHORT);
701 }
702
703
704
705
706
707
708
709 public static short toShort(byte[] bytes, int offset) {
710 return toShort(bytes, offset, SIZEOF_SHORT);
711 }
712
713
714
715
716
717
718
719
720
721
722 public static short toShort(byte[] bytes, int offset, final int length) {
723 if (length != SIZEOF_SHORT || offset + length > bytes.length) {
724 throw explainWrongLengthOrOffset(bytes, offset, length, SIZEOF_SHORT);
725 }
726 short n = 0;
727 n ^= bytes[offset] & 0xFF;
728 n <<= 8;
729 n ^= bytes[offset+1] & 0xFF;
730 return n;
731 }
732
733
734
735
736
737
738
739
740
741
742 public static int putShort(byte[] bytes, int offset, short val) {
743 if (bytes.length - offset < SIZEOF_SHORT) {
744 throw new IllegalArgumentException("Not enough room to put a short at"
745 + " offset " + offset + " in a " + bytes.length + " byte array");
746 }
747 bytes[offset+1] = (byte) val;
748 val >>= 8;
749 bytes[offset] = (byte) val;
750 return offset + SIZEOF_SHORT;
751 }
752
753
754
755
756
757 public static byte [] vintToBytes(final long vint) {
758 long i = vint;
759 int size = WritableUtils.getVIntSize(i);
760 byte [] result = new byte[size];
761 int offset = 0;
762 if (i >= -112 && i <= 127) {
763 result[offset] = (byte) i;
764 return result;
765 }
766
767 int len = -112;
768 if (i < 0) {
769 i ^= -1L;
770 len = -120;
771 }
772
773 long tmp = i;
774 while (tmp != 0) {
775 tmp = tmp >> 8;
776 len--;
777 }
778
779 result[offset++] = (byte) len;
780
781 len = (len < -120) ? -(len + 120) : -(len + 112);
782
783 for (int idx = len; idx != 0; idx--) {
784 int shiftbits = (idx - 1) * 8;
785 long mask = 0xFFL << shiftbits;
786 result[offset++] = (byte)((i & mask) >> shiftbits);
787 }
788 return result;
789 }
790
791
792
793
794
795 public static long bytesToVint(final byte [] buffer) {
796 int offset = 0;
797 byte firstByte = buffer[offset++];
798 int len = WritableUtils.decodeVIntSize(firstByte);
799 if (len == 1) {
800 return firstByte;
801 }
802 long i = 0;
803 for (int idx = 0; idx < len-1; idx++) {
804 byte b = buffer[offset++];
805 i = i << 8;
806 i = i | (b & 0xFF);
807 }
808 return (WritableUtils.isNegativeVInt(firstByte) ? ~i : i);
809 }
810
811
812
813
814
815
816
817
818 public static long readVLong(final byte [] buffer, final int offset)
819 throws IOException {
820 byte firstByte = buffer[offset];
821 int len = WritableUtils.decodeVIntSize(firstByte);
822 if (len == 1) {
823 return firstByte;
824 }
825 long i = 0;
826 for (int idx = 0; idx < len-1; idx++) {
827 byte b = buffer[offset + 1 + idx];
828 i = i << 8;
829 i = i | (b & 0xFF);
830 }
831 return (WritableUtils.isNegativeVInt(firstByte) ? ~i : i);
832 }
833
834
835
836
837
838
839 public static int compareTo(final byte [] left, final byte [] right) {
840 return compareTo(left, 0, left.length, right, 0, right.length);
841 }
842
843
844
845
846
847
848
849
850
851
852
853
854 public static int compareTo(byte[] buffer1, int offset1, int length1,
855 byte[] buffer2, int offset2, int length2) {
856
857 int end1 = offset1 + length1;
858 int end2 = offset2 + length2;
859 for (int i = offset1, j = offset2; i < end1 && j < end2; i++, j++) {
860 int a = (buffer1[i] & 0xff);
861 int b = (buffer2[j] & 0xff);
862 if (a != b) {
863 return a - b;
864 }
865 }
866 return length1 - length2;
867 }
868
869
870
871
872
873
874 public static boolean equals(final byte [] left, final byte [] right) {
875
876
877 if (left == null && right == null) {
878 return true;
879 }
880 return (left == null || right == null || (left.length != right.length)
881 ? false : compareTo(left, right) == 0);
882 }
883
884
885
886
887
888 public static boolean startsWith(byte[] bytes, byte[] prefix) {
889 return bytes != null && prefix != null &&
890 bytes.length >= prefix.length &&
891 compareTo(bytes, 0, prefix.length, prefix, 0, prefix.length) == 0;
892 }
893
894
895
896
897
898
899
900 public static int hashCode(final byte [] b) {
901 return hashCode(b, b.length);
902 }
903
904
905
906
907
908
909
910
911 public static int hashCode(final byte [] b, final int length) {
912 return WritableComparator.hashBytes(b, length);
913 }
914
915
916
917
918
919
920 public static Integer mapKey(final byte [] b) {
921 return hashCode(b);
922 }
923
924
925
926
927
928
929
930 public static Integer mapKey(final byte [] b, final int length) {
931 return hashCode(b, length);
932 }
933
934
935
936
937
938
939 public static byte [] add(final byte [] a, final byte [] b) {
940 return add(a, b, HConstants.EMPTY_BYTE_ARRAY);
941 }
942
943
944
945
946
947
948
949 public static byte [] add(final byte [] a, final byte [] b, final byte [] c) {
950 byte [] result = new byte[a.length + b.length + c.length];
951 System.arraycopy(a, 0, result, 0, a.length);
952 System.arraycopy(b, 0, result, a.length, b.length);
953 System.arraycopy(c, 0, result, a.length + b.length, c.length);
954 return result;
955 }
956
957
958
959
960
961
962 public static byte [] head(final byte [] a, final int length) {
963 if (a.length < length) {
964 return null;
965 }
966 byte [] result = new byte[length];
967 System.arraycopy(a, 0, result, 0, length);
968 return result;
969 }
970
971
972
973
974
975
976 public static byte [] tail(final byte [] a, final int length) {
977 if (a.length < length) {
978 return null;
979 }
980 byte [] result = new byte[length];
981 System.arraycopy(a, a.length - length, result, 0, length);
982 return result;
983 }
984
985
986
987
988
989
990 public static byte [] padHead(final byte [] a, final int length) {
991 byte [] padding = new byte[length];
992 for (int i = 0; i < length; i++) {
993 padding[i] = 0;
994 }
995 return add(padding,a);
996 }
997
998
999
1000
1001
1002
1003 public static byte [] padTail(final byte [] a, final int length) {
1004 byte [] padding = new byte[length];
1005 for (int i = 0; i < length; i++) {
1006 padding[i] = 0;
1007 }
1008 return add(a,padding);
1009 }
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020 public static byte [][] split(final byte [] a, final byte [] b, final int num) {
1021 byte[][] ret = new byte[num+2][];
1022 int i = 0;
1023 Iterable<byte[]> iter = iterateOnSplits(a, b, num);
1024 if (iter == null) return null;
1025 for (byte[] elem : iter) {
1026 ret[i++] = elem;
1027 }
1028 return ret;
1029 }
1030
1031
1032
1033
1034 public static Iterable<byte[]> iterateOnSplits(
1035 final byte[] a, final byte[]b, final int num)
1036 {
1037 byte [] aPadded;
1038 byte [] bPadded;
1039 if (a.length < b.length) {
1040 aPadded = padTail(a, b.length - a.length);
1041 bPadded = b;
1042 } else if (b.length < a.length) {
1043 aPadded = a;
1044 bPadded = padTail(b, a.length - b.length);
1045 } else {
1046 aPadded = a;
1047 bPadded = b;
1048 }
1049 if (compareTo(aPadded,bPadded) >= 0) {
1050 throw new IllegalArgumentException("b <= a");
1051 }
1052 if (num <= 0) {
1053 throw new IllegalArgumentException("num cannot be < 0");
1054 }
1055 byte [] prependHeader = {1, 0};
1056 final BigInteger startBI = new BigInteger(add(prependHeader, aPadded));
1057 final BigInteger stopBI = new BigInteger(add(prependHeader, bPadded));
1058 final BigInteger diffBI = stopBI.subtract(startBI);
1059 final BigInteger splitsBI = BigInteger.valueOf(num + 1);
1060 if(diffBI.compareTo(splitsBI) < 0) {
1061 return null;
1062 }
1063 final BigInteger intervalBI;
1064 try {
1065 intervalBI = diffBI.divide(splitsBI);
1066 } catch(Exception e) {
1067 LOG.error("Exception caught during division", e);
1068 return null;
1069 }
1070
1071 final Iterator<byte[]> iterator = new Iterator<byte[]>() {
1072 private int i = -1;
1073
1074 @Override
1075 public boolean hasNext() {
1076 return i < num+1;
1077 }
1078
1079 @Override
1080 public byte[] next() {
1081 i++;
1082 if (i == 0) return a;
1083 if (i == num + 1) return b;
1084
1085 BigInteger curBI = startBI.add(intervalBI.multiply(BigInteger.valueOf(i)));
1086 byte [] padded = curBI.toByteArray();
1087 if (padded[1] == 0)
1088 padded = tail(padded, padded.length - 2);
1089 else
1090 padded = tail(padded, padded.length - 1);
1091 return padded;
1092 }
1093
1094 @Override
1095 public void remove() {
1096 throw new UnsupportedOperationException();
1097 }
1098
1099 };
1100
1101 return new Iterable<byte[]>() {
1102 @Override
1103 public Iterator<byte[]> iterator() {
1104 return iterator;
1105 }
1106 };
1107 }
1108
1109
1110
1111
1112
1113 public static byte [][] toByteArrays(final String [] t) {
1114 byte [][] result = new byte[t.length][];
1115 for (int i = 0; i < t.length; i++) {
1116 result[i] = Bytes.toBytes(t[i]);
1117 }
1118 return result;
1119 }
1120
1121
1122
1123
1124
1125
1126 public static byte [][] toByteArrays(final String column) {
1127 return toByteArrays(toBytes(column));
1128 }
1129
1130
1131
1132
1133
1134
1135 public static byte [][] toByteArrays(final byte [] column) {
1136 byte [][] result = new byte[1][];
1137 result[0] = column;
1138 return result;
1139 }
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150 public static int binarySearch(byte [][]arr, byte []key, int offset,
1151 int length, RawComparator<byte []> comparator) {
1152 int low = 0;
1153 int high = arr.length - 1;
1154
1155 while (low <= high) {
1156 int mid = (low+high) >>> 1;
1157
1158
1159 int cmp = comparator.compare(key, offset, length,
1160 arr[mid], 0, arr[mid].length);
1161
1162 if (cmp > 0)
1163 low = mid + 1;
1164
1165 else if (cmp < 0)
1166 high = mid - 1;
1167
1168 else
1169 return mid;
1170 }
1171 return - (low+1);
1172 }
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183 public static byte [] incrementBytes(byte[] value, long amount)
1184 throws IOException {
1185 byte[] val = value;
1186 if (val.length < SIZEOF_LONG) {
1187
1188 byte [] newvalue;
1189 if (val[0] < 0) {
1190 newvalue = new byte[]{-1, -1, -1, -1, -1, -1, -1, -1};
1191 } else {
1192 newvalue = new byte[SIZEOF_LONG];
1193 }
1194 System.arraycopy(val, 0, newvalue, newvalue.length - val.length,
1195 val.length);
1196 val = newvalue;
1197 } else if (val.length > SIZEOF_LONG) {
1198 throw new IllegalArgumentException("Increment Bytes - value too big: " +
1199 val.length);
1200 }
1201 if(amount == 0) return val;
1202 if(val[0] < 0){
1203 return binaryIncrementNeg(val, amount);
1204 }
1205 return binaryIncrementPos(val, amount);
1206 }
1207
1208
1209 private static byte [] binaryIncrementPos(byte [] value, long amount) {
1210 long amo = amount;
1211 int sign = 1;
1212 if (amount < 0) {
1213 amo = -amount;
1214 sign = -1;
1215 }
1216 for(int i=0;i<value.length;i++) {
1217 int cur = ((int)amo % 256) * sign;
1218 amo = (amo >> 8);
1219 int val = value[value.length-i-1] & 0x0ff;
1220 int total = val + cur;
1221 if(total > 255) {
1222 amo += sign;
1223 total %= 256;
1224 } else if (total < 0) {
1225 amo -= sign;
1226 }
1227 value[value.length-i-1] = (byte)total;
1228 if (amo == 0) return value;
1229 }
1230 return value;
1231 }
1232
1233
1234 private static byte [] binaryIncrementNeg(byte [] value, long amount) {
1235 long amo = amount;
1236 int sign = 1;
1237 if (amount < 0) {
1238 amo = -amount;
1239 sign = -1;
1240 }
1241 for(int i=0;i<value.length;i++) {
1242 int cur = ((int)amo % 256) * sign;
1243 amo = (amo >> 8);
1244 int val = ((~value[value.length-i-1]) & 0x0ff) + 1;
1245 int total = cur - val;
1246 if(total >= 0) {
1247 amo += sign;
1248 } else if (total < -256) {
1249 amo -= sign;
1250 total %= 256;
1251 }
1252 value[value.length-i-1] = (byte)total;
1253 if (amo == 0) return value;
1254 }
1255 return value;
1256 }
1257
1258 }