001/* 002 * Licensed to the Apache Software Foundation (ASF) under one 003 * or more contributor license agreements. See the NOTICE file 004 * distributed with this work for additional information 005 * regarding copyright ownership. The ASF licenses this file 006 * to you under the Apache License, Version 2.0 (the 007 * "License"); you may not use this file except in compliance 008 * with the License. You may obtain a copy of the License at 009 * 010 * http://www.apache.org/licenses/LICENSE-2.0 011 * 012 * Unless required by applicable law or agreed to in writing, software 013 * distributed under the License is distributed on an "AS IS" BASIS, 014 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 015 * See the License for the specific language governing permissions and 016 * limitations under the License. 017 */ 018package org.apache.hadoop.hbase.util; 019 020import java.io.ByteArrayOutputStream; 021import java.io.DataInput; 022import java.io.DataInputStream; 023import java.io.DataOutput; 024import java.io.IOException; 025import java.io.InputStream; 026import java.io.OutputStream; 027import java.math.BigDecimal; 028import java.math.BigInteger; 029import java.nio.ByteBuffer; 030import java.util.Arrays; 031import org.apache.hadoop.hbase.io.ByteBufferWriter; 032import org.apache.hadoop.hbase.io.util.StreamUtils; 033import org.apache.hadoop.hbase.nio.ByteBuff; 034import org.apache.hadoop.hbase.unsafe.HBasePlatformDependent; 035import org.apache.hadoop.io.IOUtils; 036import org.apache.hadoop.io.WritableUtils; 037import org.apache.yetus.audience.InterfaceAudience; 038 039/** 040 * Utility functions for working with byte buffers, such as reading/writing variable-length long 041 * numbers. 042 * @deprecated This class will become IA.Private in HBase 3.0. Downstream folks shouldn't use it. 043 */ 044@Deprecated 045@InterfaceAudience.Public 046public final class ByteBufferUtils { 047 // "Compressed integer" serialization helper constants. 048 public final static int VALUE_MASK = 0x7f; 049 public final static int NEXT_BIT_SHIFT = 7; 050 public final static int NEXT_BIT_MASK = 1 << 7; 051 @InterfaceAudience.Private 052 final static boolean UNSAFE_AVAIL = HBasePlatformDependent.isUnsafeAvailable(); 053 public final static boolean UNSAFE_UNALIGNED = HBasePlatformDependent.unaligned(); 054 055 private ByteBufferUtils() { 056 } 057 058 static abstract class Comparer { 059 abstract int compareTo(byte[] buf1, int o1, int l1, ByteBuffer buf2, int o2, int l2); 060 061 abstract int compareTo(ByteBuffer buf1, int o1, int l1, ByteBuffer buf2, int o2, int l2); 062 } 063 064 static abstract class Converter { 065 abstract short toShort(ByteBuffer buffer, int offset); 066 067 abstract int toInt(ByteBuffer buffer); 068 069 abstract int toInt(ByteBuffer buffer, int offset); 070 071 abstract long toLong(ByteBuffer buffer, int offset); 072 073 abstract void putInt(ByteBuffer buffer, int val); 074 075 abstract int putInt(ByteBuffer buffer, int index, int val); 076 077 abstract void putShort(ByteBuffer buffer, short val); 078 079 abstract int putShort(ByteBuffer buffer, int index, short val); 080 081 abstract void putLong(ByteBuffer buffer, long val); 082 083 abstract int putLong(ByteBuffer buffer, int index, long val); 084 } 085 086 static abstract class CommonPrefixer { 087 abstract int findCommonPrefix(ByteBuffer left, int leftOffset, int leftLength, byte[] right, 088 int rightOffset, int rightLength); 089 090 abstract int findCommonPrefix(ByteBuffer left, int leftOffset, int leftLength, ByteBuffer right, 091 int rightOffset, int rightLength); 092 } 093 094 static class ComparerHolder { 095 static final String UNSAFE_COMPARER_NAME = ComparerHolder.class.getName() + "$UnsafeComparer"; 096 097 static final Comparer BEST_COMPARER = getBestComparer(); 098 099 static Comparer getBestComparer() { 100 try { 101 Class<? extends Comparer> theClass = 102 Class.forName(UNSAFE_COMPARER_NAME).asSubclass(Comparer.class); 103 104 return theClass.getConstructor().newInstance(); 105 } catch (Throwable t) { // ensure we really catch *everything* 106 return PureJavaComparer.INSTANCE; 107 } 108 } 109 110 static final class PureJavaComparer extends Comparer { 111 static final PureJavaComparer INSTANCE = new PureJavaComparer(); 112 113 private PureJavaComparer() { 114 } 115 116 @Override 117 public int compareTo(byte[] buf1, int o1, int l1, ByteBuffer buf2, int o2, int l2) { 118 int end1 = o1 + l1; 119 int end2 = o2 + l2; 120 for (int i = o1, j = o2; i < end1 && j < end2; i++, j++) { 121 int a = buf1[i] & 0xFF; 122 int b = buf2.get(j) & 0xFF; 123 if (a != b) { 124 return a - b; 125 } 126 } 127 return l1 - l2; 128 } 129 130 @Override 131 public int compareTo(ByteBuffer buf1, int o1, int l1, ByteBuffer buf2, int o2, int l2) { 132 int end1 = o1 + l1; 133 int end2 = o2 + l2; 134 for (int i = o1, j = o2; i < end1 && j < end2; i++, j++) { 135 int a = buf1.get(i) & 0xFF; 136 int b = buf2.get(j) & 0xFF; 137 if (a != b) { 138 return a - b; 139 } 140 } 141 return l1 - l2; 142 } 143 } 144 145 static final class UnsafeComparer extends Comparer { 146 147 public UnsafeComparer() { 148 } 149 150 static { 151 if (!UNSAFE_UNALIGNED) { 152 throw new Error(); 153 } 154 } 155 156 @Override 157 public int compareTo(byte[] buf1, int o1, int l1, ByteBuffer buf2, int o2, int l2) { 158 long offset2Adj; 159 Object refObj2 = null; 160 if (buf2.isDirect()) { 161 offset2Adj = o2 + UnsafeAccess.directBufferAddress(buf2); 162 } else { 163 offset2Adj = o2 + buf2.arrayOffset() + UnsafeAccess.BYTE_ARRAY_BASE_OFFSET; 164 refObj2 = buf2.array(); 165 } 166 return compareToUnsafe(buf1, o1 + UnsafeAccess.BYTE_ARRAY_BASE_OFFSET, l1, refObj2, 167 offset2Adj, l2); 168 } 169 170 @Override 171 public int compareTo(ByteBuffer buf1, int o1, int l1, ByteBuffer buf2, int o2, int l2) { 172 long offset1Adj, offset2Adj; 173 Object refObj1 = null, refObj2 = null; 174 if (buf1.isDirect()) { 175 offset1Adj = o1 + UnsafeAccess.directBufferAddress(buf1); 176 } else { 177 offset1Adj = o1 + buf1.arrayOffset() + UnsafeAccess.BYTE_ARRAY_BASE_OFFSET; 178 refObj1 = buf1.array(); 179 } 180 if (buf2.isDirect()) { 181 offset2Adj = o2 + UnsafeAccess.directBufferAddress(buf2); 182 } else { 183 offset2Adj = o2 + buf2.arrayOffset() + UnsafeAccess.BYTE_ARRAY_BASE_OFFSET; 184 refObj2 = buf2.array(); 185 } 186 return compareToUnsafe(refObj1, offset1Adj, l1, refObj2, offset2Adj, l2); 187 } 188 } 189 } 190 191 static class ConverterHolder { 192 static final String UNSAFE_CONVERTER_NAME = 193 ConverterHolder.class.getName() + "$UnsafeConverter"; 194 static final Converter BEST_CONVERTER = getBestConverter(); 195 196 static Converter getBestConverter() { 197 try { 198 Class<? extends Converter> theClass = 199 Class.forName(UNSAFE_CONVERTER_NAME).asSubclass(Converter.class); 200 201 // yes, UnsafeComparer does implement Comparer<byte[]> 202 return theClass.getConstructor().newInstance(); 203 } catch (Throwable t) { // ensure we really catch *everything* 204 return PureJavaConverter.INSTANCE; 205 } 206 } 207 208 static final class PureJavaConverter extends Converter { 209 static final PureJavaConverter INSTANCE = new PureJavaConverter(); 210 211 private PureJavaConverter() { 212 } 213 214 @Override 215 short toShort(ByteBuffer buffer, int offset) { 216 return buffer.getShort(offset); 217 } 218 219 @Override 220 int toInt(ByteBuffer buffer) { 221 return buffer.getInt(); 222 } 223 224 @Override 225 int toInt(ByteBuffer buffer, int offset) { 226 return buffer.getInt(offset); 227 } 228 229 @Override 230 long toLong(ByteBuffer buffer, int offset) { 231 return buffer.getLong(offset); 232 } 233 234 @Override 235 void putInt(ByteBuffer buffer, int val) { 236 buffer.putInt(val); 237 } 238 239 @Override 240 int putInt(ByteBuffer buffer, int index, int val) { 241 buffer.putInt(index, val); 242 return index + Bytes.SIZEOF_INT; 243 } 244 245 @Override 246 void putShort(ByteBuffer buffer, short val) { 247 buffer.putShort(val); 248 } 249 250 @Override 251 int putShort(ByteBuffer buffer, int index, short val) { 252 buffer.putShort(index, val); 253 return index + Bytes.SIZEOF_SHORT; 254 } 255 256 @Override 257 void putLong(ByteBuffer buffer, long val) { 258 buffer.putLong(val); 259 } 260 261 @Override 262 int putLong(ByteBuffer buffer, int index, long val) { 263 buffer.putLong(index, val); 264 return index + Bytes.SIZEOF_LONG; 265 } 266 } 267 268 static final class UnsafeConverter extends Converter { 269 270 public UnsafeConverter() { 271 } 272 273 static { 274 if (!UNSAFE_UNALIGNED) { 275 throw new Error(); 276 } 277 } 278 279 @Override 280 short toShort(ByteBuffer buffer, int offset) { 281 return UnsafeAccess.toShort(buffer, offset); 282 } 283 284 @Override 285 int toInt(ByteBuffer buffer) { 286 int i = UnsafeAccess.toInt(buffer, buffer.position()); 287 buffer.position(buffer.position() + Bytes.SIZEOF_INT); 288 return i; 289 } 290 291 @Override 292 int toInt(ByteBuffer buffer, int offset) { 293 return UnsafeAccess.toInt(buffer, offset); 294 } 295 296 @Override 297 long toLong(ByteBuffer buffer, int offset) { 298 return UnsafeAccess.toLong(buffer, offset); 299 } 300 301 @Override 302 void putInt(ByteBuffer buffer, int val) { 303 int newPos = UnsafeAccess.putInt(buffer, buffer.position(), val); 304 buffer.position(newPos); 305 } 306 307 @Override 308 int putInt(ByteBuffer buffer, int index, int val) { 309 return UnsafeAccess.putInt(buffer, index, val); 310 } 311 312 @Override 313 void putShort(ByteBuffer buffer, short val) { 314 int newPos = UnsafeAccess.putShort(buffer, buffer.position(), val); 315 buffer.position(newPos); 316 } 317 318 @Override 319 int putShort(ByteBuffer buffer, int index, short val) { 320 return UnsafeAccess.putShort(buffer, index, val); 321 } 322 323 @Override 324 void putLong(ByteBuffer buffer, long val) { 325 int newPos = UnsafeAccess.putLong(buffer, buffer.position(), val); 326 buffer.position(newPos); 327 } 328 329 @Override 330 int putLong(ByteBuffer buffer, int index, long val) { 331 return UnsafeAccess.putLong(buffer, index, val); 332 } 333 } 334 } 335 336 static class CommonPrefixerHolder { 337 static final String UNSAFE_COMMON_PREFIXER_NAME = 338 CommonPrefixerHolder.class.getName() + "$UnsafeCommonPrefixer"; 339 340 static final CommonPrefixer BEST_COMMON_PREFIXER = getBestCommonPrefixer(); 341 342 static CommonPrefixer getBestCommonPrefixer() { 343 try { 344 Class<? extends CommonPrefixer> theClass = 345 Class.forName(UNSAFE_COMMON_PREFIXER_NAME).asSubclass(CommonPrefixer.class); 346 347 return theClass.getConstructor().newInstance(); 348 } catch (Throwable t) { // ensure we really catch *everything* 349 return PureJavaCommonPrefixer.INSTANCE; 350 } 351 } 352 353 static final class PureJavaCommonPrefixer extends CommonPrefixer { 354 static final PureJavaCommonPrefixer INSTANCE = new PureJavaCommonPrefixer(); 355 356 private PureJavaCommonPrefixer() { 357 } 358 359 @Override 360 public int findCommonPrefix(ByteBuffer left, int leftOffset, int leftLength, byte[] right, 361 int rightOffset, int rightLength) { 362 int length = Math.min(leftLength, rightLength); 363 int result = 0; 364 365 while ( 366 result < length 367 && ByteBufferUtils.toByte(left, leftOffset + result) == right[rightOffset + result] 368 ) { 369 result++; 370 } 371 372 return result; 373 } 374 375 @Override 376 int findCommonPrefix(ByteBuffer left, int leftOffset, int leftLength, ByteBuffer right, 377 int rightOffset, int rightLength) { 378 int length = Math.min(leftLength, rightLength); 379 int result = 0; 380 381 while ( 382 result < length && ByteBufferUtils.toByte(left, leftOffset + result) 383 == ByteBufferUtils.toByte(right, rightOffset + result) 384 ) { 385 result++; 386 } 387 388 return result; 389 } 390 } 391 392 static final class UnsafeCommonPrefixer extends CommonPrefixer { 393 394 static { 395 if (!UNSAFE_UNALIGNED) { 396 throw new Error(); 397 } 398 } 399 400 public UnsafeCommonPrefixer() { 401 } 402 403 @Override 404 public int findCommonPrefix(ByteBuffer left, int leftOffset, int leftLength, byte[] right, 405 int rightOffset, int rightLength) { 406 long offset1Adj; 407 Object refObj1 = null; 408 if (left.isDirect()) { 409 offset1Adj = leftOffset + UnsafeAccess.directBufferAddress(left); 410 } else { 411 offset1Adj = leftOffset + left.arrayOffset() + UnsafeAccess.BYTE_ARRAY_BASE_OFFSET; 412 refObj1 = left.array(); 413 } 414 return findCommonPrefixUnsafe(refObj1, offset1Adj, leftLength, right, 415 rightOffset + UnsafeAccess.BYTE_ARRAY_BASE_OFFSET, rightLength); 416 } 417 418 @Override 419 public int findCommonPrefix(ByteBuffer left, int leftOffset, int leftLength, ByteBuffer right, 420 int rightOffset, int rightLength) { 421 long offset1Adj, offset2Adj; 422 Object refObj1 = null, refObj2 = null; 423 if (left.isDirect()) { 424 offset1Adj = leftOffset + UnsafeAccess.directBufferAddress(left); 425 } else { 426 offset1Adj = leftOffset + left.arrayOffset() + UnsafeAccess.BYTE_ARRAY_BASE_OFFSET; 427 refObj1 = left.array(); 428 } 429 if (right.isDirect()) { 430 offset2Adj = rightOffset + UnsafeAccess.directBufferAddress(right); 431 } else { 432 offset2Adj = rightOffset + right.arrayOffset() + UnsafeAccess.BYTE_ARRAY_BASE_OFFSET; 433 refObj2 = right.array(); 434 } 435 return findCommonPrefixUnsafe(refObj1, offset1Adj, leftLength, refObj2, offset2Adj, 436 rightLength); 437 } 438 } 439 } 440 441 /** 442 * Similar to {@link WritableUtils#writeVLong(java.io.DataOutput, long)}, but writes to a 443 * {@link ByteBuffer}. 444 */ 445 public static void writeVLong(ByteBuffer out, long i) { 446 if (i >= -112 && i <= 127) { 447 out.put((byte) i); 448 return; 449 } 450 451 int len = -112; 452 if (i < 0) { 453 i ^= -1L; // take one's complement 454 len = -120; 455 } 456 457 long tmp = i; 458 while (tmp != 0) { 459 tmp = tmp >> 8; 460 len--; 461 } 462 463 out.put((byte) len); 464 465 len = (len < -120) ? -(len + 120) : -(len + 112); 466 467 for (int idx = len; idx != 0; idx--) { 468 int shiftbits = (idx - 1) * 8; 469 long mask = 0xFFL << shiftbits; 470 out.put((byte) ((i & mask) >> shiftbits)); 471 } 472 } 473 474 private interface ByteVisitor { 475 byte get(); 476 } 477 478 private static long readVLong(ByteVisitor visitor) { 479 byte firstByte = visitor.get(); 480 int len = WritableUtils.decodeVIntSize(firstByte); 481 if (len == 1) { 482 return firstByte; 483 } 484 long i = 0; 485 for (int idx = 0; idx < len - 1; idx++) { 486 byte b = visitor.get(); 487 i = i << 8; 488 i = i | (b & 0xFF); 489 } 490 return (WritableUtils.isNegativeVInt(firstByte) ? (i ^ -1L) : i); 491 } 492 493 /** 494 * Similar to {@link WritableUtils#readVLong(DataInput)} but reads from a {@link ByteBuffer}. 495 */ 496 public static long readVLong(ByteBuffer in) { 497 return readVLong(in::get); 498 } 499 500 /** 501 * Similar to {@link WritableUtils#readVLong(java.io.DataInput)} but reads from a 502 * {@link ByteBuff}. 503 */ 504 public static long readVLong(ByteBuff in) { 505 return readVLong(in::get); 506 } 507 508 /** 509 * Put in buffer integer using 7 bit encoding. For each written byte: 7 bits are used to store 510 * value 1 bit is used to indicate whether there is next bit. 511 * @param value Int to be compressed. 512 * @param out Where to put compressed data 513 * @return Number of bytes written. 514 * @throws IOException on stream error 515 */ 516 public static int putCompressedInt(OutputStream out, final int value) throws IOException { 517 int i = 0; 518 int tmpvalue = value; 519 do { 520 byte b = (byte) (tmpvalue & VALUE_MASK); 521 tmpvalue >>>= NEXT_BIT_SHIFT; 522 if (tmpvalue != 0) { 523 b |= (byte) NEXT_BIT_MASK; 524 } 525 out.write(b); 526 i++; 527 } while (tmpvalue != 0); 528 return i; 529 } 530 531 /** 532 * Put in output stream 32 bit integer (Big Endian byte order). 533 * @param out Where to put integer. 534 * @param value Value of integer. 535 * @throws IOException On stream error. 536 */ 537 public static void putInt(OutputStream out, final int value) throws IOException { 538 // We have writeInt in ByteBufferOutputStream so that it can directly write 539 // int to underlying 540 // ByteBuffer in one step. 541 if (out instanceof ByteBufferWriter) { 542 ((ByteBufferWriter) out).writeInt(value); 543 } else { 544 StreamUtils.writeInt(out, value); 545 } 546 } 547 548 public static byte toByte(ByteBuffer buffer, int offset) { 549 if (UNSAFE_AVAIL) { 550 return UnsafeAccess.toByte(buffer, offset); 551 } else { 552 return buffer.get(offset); 553 } 554 } 555 556 /** 557 * Copy the data to the output stream and update position in buffer. 558 * @param out the stream to write bytes to 559 * @param in the buffer to read bytes from 560 * @param length the number of bytes to copy 561 */ 562 public static void moveBufferToStream(OutputStream out, ByteBuffer in, int length) 563 throws IOException { 564 copyBufferToStream(out, in, in.position(), length); 565 skip(in, length); 566 } 567 568 /** 569 * Copy data from a buffer to an output stream. Does not update the position in the buffer. 570 * @param out the stream to write bytes to 571 * @param in the buffer to read bytes from 572 * @param offset the offset in the buffer (from the buffer's array offset) to start copying bytes 573 * from 574 * @param length the number of bytes to copy 575 */ 576 public static void copyBufferToStream(OutputStream out, ByteBuffer in, int offset, int length) 577 throws IOException { 578 if (out instanceof ByteBufferWriter) { 579 ((ByteBufferWriter) out).write(in, offset, length); 580 } else if (in.hasArray()) { 581 out.write(in.array(), in.arrayOffset() + offset, length); 582 } else { 583 for (int i = 0; i < length; ++i) { 584 out.write(toByte(in, offset + i)); 585 } 586 } 587 } 588 589 /** 590 * Copy data from a buffer to an output stream. Does not update the position in the buffer. 591 * @param out the output stream to write bytes to 592 * @param in the buffer to read bytes from 593 * @param offset the offset in the buffer (from the buffer's array offset) to start copying bytes 594 * from 595 * @param length the number of bytes to copy 596 */ 597 public static void copyBufferToStream(DataOutput out, ByteBuffer in, int offset, int length) 598 throws IOException { 599 if (out instanceof ByteBufferWriter) { 600 ((ByteBufferWriter) out).write(in, offset, length); 601 } else if (in.hasArray()) { 602 out.write(in.array(), in.arrayOffset() + offset, length); 603 } else { 604 for (int i = 0; i < length; ++i) { 605 out.write(toByte(in, offset + i)); 606 } 607 } 608 } 609 610 public static int putLong(OutputStream out, final long value, final int fitInBytes) 611 throws IOException { 612 long tmpValue = value; 613 for (int i = 0; i < fitInBytes; ++i) { 614 out.write((byte) (tmpValue & 0xff)); 615 tmpValue >>>= 8; 616 } 617 return fitInBytes; 618 } 619 620 public static int putByte(ByteBuffer buffer, int offset, byte b) { 621 if (UNSAFE_AVAIL) { 622 return UnsafeAccess.putByte(buffer, offset, b); 623 } else { 624 buffer.put(offset, b); 625 return offset + 1; 626 } 627 } 628 629 /** 630 * Check how many bytes are required to store value. 631 * @param value Value which size will be tested. 632 * @return How many bytes are required to store value. 633 */ 634 public static int longFitsIn(final long value) { 635 if (value < 0) { 636 return 8; 637 } 638 639 if (value < (1L << (4 * 8))) { 640 // no more than 4 bytes 641 if (value < (1L << (2 * 8))) { 642 if (value < (1L << (1 * 8))) { 643 return 1; 644 } 645 return 2; 646 } 647 if (value < (1L << (3 * 8))) { 648 return 3; 649 } 650 return 4; 651 } 652 // more than 4 bytes 653 if (value < (1L << (6 * 8))) { 654 if (value < (1L << (5 * 8))) { 655 return 5; 656 } 657 return 6; 658 } 659 if (value < (1L << (7 * 8))) { 660 return 7; 661 } 662 return 8; 663 } 664 665 /** 666 * Check how many bytes is required to store value. 667 * @param value Value which size will be tested. 668 * @return How many bytes are required to store value. 669 */ 670 public static int intFitsIn(final int value) { 671 if (value < 0) { 672 return 4; 673 } 674 675 if (value < (1 << (2 * 8))) { 676 if (value < (1 << (1 * 8))) { 677 return 1; 678 } 679 return 2; 680 } 681 if (value <= (1 << (3 * 8))) { 682 return 3; 683 } 684 return 4; 685 } 686 687 /** 688 * Read integer from stream coded in 7 bits and increment position. 689 * @return the integer that has been read 690 * @throws IOException on stream error 691 */ 692 public static int readCompressedInt(InputStream input) throws IOException { 693 int result = 0; 694 int i = 0; 695 byte b; 696 do { 697 b = (byte) input.read(); 698 result += (b & VALUE_MASK) << (NEXT_BIT_SHIFT * i); 699 i++; 700 if (i > Bytes.SIZEOF_INT + 1) { 701 throw new IllegalStateException( 702 "Corrupted compressed int (too long: " + (i + 1) + " bytes)"); 703 } 704 } while (0 != (b & NEXT_BIT_MASK)); 705 return result; 706 } 707 708 /** 709 * Read integer from buffer coded in 7 bits and increment position. 710 * @return Read integer. 711 */ 712 public static int readCompressedInt(ByteBuffer buffer) { 713 byte b = buffer.get(); 714 if ((b & NEXT_BIT_MASK) != 0) { 715 return (b & VALUE_MASK) + (readCompressedInt(buffer) << NEXT_BIT_SHIFT); 716 } 717 return b & VALUE_MASK; 718 } 719 720 /** 721 * Read long which was written to fitInBytes bytes and increment position. 722 * @param fitInBytes In how many bytes given long is stored. 723 * @return The value of parsed long. 724 * @throws IOException on stream error 725 */ 726 public static long readLong(InputStream in, final int fitInBytes) throws IOException { 727 long tmpLong = 0; 728 for (int i = 0; i < fitInBytes; ++i) { 729 tmpLong |= (in.read() & 0xffL) << (8 * i); 730 } 731 return tmpLong; 732 } 733 734 /** 735 * Read long which was written to fitInBytes bytes and increment position. 736 * @param fitInBytes In how many bytes given long is stored. 737 * @return The value of parsed long. 738 */ 739 public static long readLong(ByteBuffer in, final int fitInBytes) { 740 long tmpLength = 0; 741 for (int i = 0; i < fitInBytes; ++i) { 742 tmpLength |= (in.get() & 0xffL) << (8L * i); 743 } 744 return tmpLength; 745 } 746 747 /** 748 * Copy the given number of bytes from the given stream and put it at the current position of the 749 * given buffer, updating the position in the buffer. 750 * @param out the buffer to write data to 751 * @param in the stream to read data from 752 * @param length the number of bytes to read/write 753 */ 754 public static void copyFromStreamToBuffer(ByteBuffer out, DataInputStream in, int length) 755 throws IOException { 756 if (out.hasArray()) { 757 in.readFully(out.array(), out.position() + out.arrayOffset(), length); 758 skip(out, length); 759 } else { 760 for (int i = 0; i < length; ++i) { 761 out.put(in.readByte()); 762 } 763 } 764 } 765 766 /** 767 * Copy from the InputStream to a new heap ByteBuffer until the InputStream is exhausted. 768 */ 769 public static ByteBuffer drainInputStreamToBuffer(InputStream is) throws IOException { 770 ByteArrayOutputStream baos = new ByteArrayOutputStream(4096); 771 IOUtils.copyBytes(is, baos, 4096, true); 772 ByteBuffer buffer = ByteBuffer.wrap(baos.toByteArray()); 773 buffer.rewind(); 774 return buffer; 775 } 776 777 /** 778 * Copy one buffer's whole data to another. Write starts at the current position of 'out' buffer. 779 * Note : This will advance the position marker of {@code out} and also change the position maker 780 * for {@code in}. 781 * @param in source buffer 782 * @param out destination buffer 783 */ 784 public static void copyFromBufferToBuffer(ByteBuffer in, ByteBuffer out) { 785 if (in.hasArray() && out.hasArray()) { 786 int length = in.remaining(); 787 System.arraycopy(in.array(), in.arrayOffset(), out.array(), out.arrayOffset(), length); 788 out.position(out.position() + length); 789 in.position(in.limit()); 790 } else if (UNSAFE_AVAIL) { 791 int length = in.remaining(); 792 UnsafeAccess.copy(in, in.position(), out, out.position(), length); 793 out.position(out.position() + length); 794 in.position(in.limit()); 795 } else { 796 out.put(in); 797 } 798 } 799 800 /** 801 * Copy from one buffer to another from given offset. This will be absolute positional copying and 802 * won't affect the position of any of the buffers. 803 * @param in input bytebuffer 804 * @param out destination bytebuffer 805 * @param sourceOffset offset of source buffer 806 * @param destinationOffset offset of destination buffer 807 * @param length the number of bytes to copy 808 */ 809 public static void copyFromBufferToBuffer(ByteBuffer in, ByteBuffer out, int sourceOffset, 810 int destinationOffset, int length) { 811 if (in.hasArray() && out.hasArray()) { 812 System.arraycopy(in.array(), sourceOffset + in.arrayOffset(), out.array(), 813 out.arrayOffset() + destinationOffset, length); 814 } else if (UNSAFE_AVAIL) { 815 UnsafeAccess.copy(in, sourceOffset, out, destinationOffset, length); 816 } else { 817 ByteBuffer outDup = out.duplicate(); 818 outDup.position(destinationOffset); 819 ByteBuffer inDup = in.duplicate(); 820 inDup.position(sourceOffset).limit(sourceOffset + length); 821 outDup.put(inDup); 822 } 823 // We used to return a result but disabled; return destinationOffset + length; 824 } 825 826 /** 827 * Copy from one buffer to another from given offset. 828 * <p> 829 * Note : This will advance the position marker of {@code out} but not change the position maker 830 * for {@code in} 831 * @param in source buffer 832 * @param out destination buffer 833 * @param sourceOffset offset in the source buffer 834 * @param length how many bytes to copy 835 */ 836 public static void copyFromBufferToBuffer(ByteBuffer in, ByteBuffer out, int sourceOffset, 837 int length) { 838 if (in.hasArray() && out.hasArray()) { 839 System.arraycopy(in.array(), sourceOffset + in.arrayOffset(), out.array(), 840 out.position() + out.arrayOffset(), length); 841 skip(out, length); 842 } else if (UNSAFE_AVAIL) { 843 UnsafeAccess.copy(in, sourceOffset, out, out.position(), length); 844 skip(out, length); 845 } else { 846 ByteBuffer inDup = in.duplicate(); 847 inDup.position(sourceOffset).limit(sourceOffset + length); 848 out.put(inDup); 849 } 850 } 851 852 /** 853 * Find length of common prefix of two parts in the buffer 854 * @param buffer Where parts are located. 855 * @param offsetLeft Offset of the first part. 856 * @param offsetRight Offset of the second part. 857 * @param limit Maximal length of common prefix. 858 * @return Length of prefix. 859 */ 860 @SuppressWarnings("unused") 861 public static int findCommonPrefix(ByteBuffer buffer, int offsetLeft, int offsetRight, 862 int limit) { 863 int prefix = 0; 864 865 for (; prefix < limit; ++prefix) { 866 if (buffer.get(offsetLeft + prefix) != buffer.get(offsetRight + prefix)) { 867 break; 868 } 869 } 870 871 return prefix; 872 } 873 874 /** 875 * Find length of common prefix in two arrays. 876 * @param left Array to be compared. 877 * @param leftOffset Offset in left array. 878 * @param leftLength Length of left array. 879 * @param right Array to be compared. 880 * @param rightOffset Offset in right array. 881 * @param rightLength Length of right array. 882 */ 883 public static int findCommonPrefix(byte[] left, int leftOffset, int leftLength, byte[] right, 884 int rightOffset, int rightLength) { 885 return Bytes.findCommonPrefix(left, right, leftLength, rightLength, leftOffset, rightOffset); 886 } 887 888 /** 889 * Find length of common prefix in two arrays. 890 * @param left ByteBuffer to be compared. 891 * @param leftOffset Offset in left ByteBuffer. 892 * @param leftLength Length of left ByteBuffer. 893 * @param right ByteBuffer to be compared. 894 * @param rightOffset Offset in right ByteBuffer. 895 * @param rightLength Length of right ByteBuffer. 896 */ 897 public static int findCommonPrefix(ByteBuffer left, int leftOffset, int leftLength, 898 ByteBuffer right, int rightOffset, int rightLength) { 899 return CommonPrefixerHolder.BEST_COMMON_PREFIXER.findCommonPrefix(left, leftOffset, leftLength, 900 right, rightOffset, rightLength); 901 } 902 903 /** 904 * Find length of common prefix in two arrays. 905 * @param left ByteBuffer to be compared. 906 * @param leftOffset Offset in left ByteBuffer. 907 * @param leftLength Length of left ByteBuffer. 908 * @param right Array to be compared 909 * @param rightOffset Offset in right Array. 910 * @param rightLength Length of right Array. 911 */ 912 public static int findCommonPrefix(ByteBuffer left, int leftOffset, int leftLength, byte[] right, 913 int rightOffset, int rightLength) { 914 return CommonPrefixerHolder.BEST_COMMON_PREFIXER.findCommonPrefix(left, leftOffset, leftLength, 915 right, rightOffset, rightLength); 916 } 917 918 /** 919 * Check whether two parts in the same buffer are equal. 920 * @param buffer In which buffer there are parts 921 * @param offsetLeft Beginning of first part. 922 * @param lengthLeft Length of the first part. 923 * @param offsetRight Beginning of the second part. 924 * @param lengthRight Length of the second part. 925 * @return True if equal 926 */ 927 public static boolean arePartsEqual(ByteBuffer buffer, int offsetLeft, int lengthLeft, 928 int offsetRight, int lengthRight) { 929 if (lengthLeft != lengthRight) { 930 return false; 931 } 932 933 if (buffer.hasArray()) { 934 return 0 == Bytes.compareTo(buffer.array(), buffer.arrayOffset() + offsetLeft, lengthLeft, 935 buffer.array(), buffer.arrayOffset() + offsetRight, lengthRight); 936 } 937 938 for (int i = 0; i < lengthRight; ++i) { 939 if (buffer.get(offsetLeft + i) != buffer.get(offsetRight + i)) { 940 return false; 941 } 942 } 943 return true; 944 } 945 946 /** 947 * Increment position in buffer. 948 * @param buffer In this buffer. 949 * @param length By that many bytes. 950 */ 951 public static void skip(ByteBuffer buffer, int length) { 952 buffer.position(buffer.position() + length); 953 } 954 955 public static void extendLimit(ByteBuffer buffer, int numBytes) { 956 buffer.limit(buffer.limit() + numBytes); 957 } 958 959 /** 960 * Copy the bytes from position to limit into a new byte[] of the exact length and sets the 961 * position and limit back to their original values (though not thread safe). 962 * @param buffer copy from here 963 * @param startPosition put buffer.get(startPosition) into byte[0] 964 * @return a new byte[] containing the bytes in the specified range 965 */ 966 public static byte[] toBytes(ByteBuffer buffer, int startPosition) { 967 int originalPosition = buffer.position(); 968 byte[] output = new byte[buffer.limit() - startPosition]; 969 buffer.position(startPosition); 970 buffer.get(output); 971 buffer.position(originalPosition); 972 return output; 973 } 974 975 /** 976 * Copy the given number of bytes from specified offset into a new byte[] 977 * @param buffer input bytebuffer to read 978 * @param offset input offset where Bytes are 979 * @param length the number of bytes to read 980 * @return a new byte[] containing the bytes in the specified range 981 */ 982 public static byte[] toBytes(ByteBuffer buffer, int offset, int length) { 983 byte[] output = new byte[length]; 984 for (int i = 0; i < length; i++) { 985 output[i] = buffer.get(offset + i); 986 } 987 return output; 988 } 989 990 public static boolean equals(ByteBuffer buf1, int o1, int l1, ByteBuffer buf2, int o2, int l2) { 991 if ((l1 == 0) || (l2 == 0)) { 992 // both 0 length, return true, or else false 993 return l1 == l2; 994 } 995 // Since we're often comparing adjacent sorted data, 996 // it's usual to have equal arrays except for the very last byte 997 // so check that first 998 if (toByte(buf1, o1 + l1 - 1) != toByte(buf2, o2 + l2 - 1)) { 999 return false; 1000 } 1001 return compareTo(buf1, o1, l1, buf2, o2, l2) == 0; 1002 } 1003 1004 /** 1005 * ByteBuffer to hash offset to start from length to hash 1006 */ 1007 public static int hashCode(ByteBuffer buf, int offset, int length) { 1008 int hash = 1; 1009 for (int i = offset; i < offset + length; i++) { 1010 hash = (31 * hash) + (int) toByte(buf, i); 1011 } 1012 return hash; 1013 } 1014 1015 public static int compareTo(ByteBuffer buf1, int o1, int l1, ByteBuffer buf2, int o2, int l2) { 1016 return ComparerHolder.BEST_COMPARER.compareTo(buf1, o1, l1, buf2, o2, l2); 1017 } 1018 1019 public static boolean equals(ByteBuffer buf1, int o1, int l1, byte[] buf2, int o2, int l2) { 1020 if ((l1 == 0) || (l2 == 0)) { 1021 // both 0 length, return true, or else false 1022 return l1 == l2; 1023 } 1024 // Since we're often comparing adjacent sorted data, 1025 // it's usual to have equal arrays except for the very last byte 1026 // so check that first 1027 if (toByte(buf1, o1 + l1 - 1) != buf2[o2 + l2 - 1]) { 1028 return false; 1029 } 1030 return compareTo(buf1, o1, l1, buf2, o2, l2) == 0; 1031 } 1032 1033 // The below two methods show up in lots of places. Versions of them in commons util and in 1034 // Cassandra. In guava too? They are copied from ByteBufferUtils. They are here as static 1035 // privates. Seems to make code smaller and make Hotspot happier (comes of compares and study 1036 // of compiled code via jitwatch). 1037 1038 public static int compareTo(byte[] buf1, int o1, int l1, ByteBuffer buf2, int o2, int l2) { 1039 return ComparerHolder.BEST_COMPARER.compareTo(buf1, o1, l1, buf2, o2, l2); 1040 } 1041 1042 public static int compareTo(ByteBuffer buf1, int o1, int l1, byte[] buf2, int o2, int l2) { 1043 return compareTo(buf2, o2, l2, buf1, o1, l1) * -1; 1044 } 1045 1046 static int compareToUnsafe(Object obj1, long o1, int l1, Object obj2, long o2, int l2) { 1047 final int stride = 8; 1048 final int minLength = Math.min(l1, l2); 1049 int strideLimit = minLength & ~(stride - 1); 1050 int i; 1051 1052 /* 1053 * Compare 8 bytes at a time. Benchmarking shows comparing 8 bytes at a time is no slower than 1054 * comparing 4 bytes at a time even on 32-bit. On the other hand, it is substantially faster on 1055 * 64-bit. 1056 */ 1057 for (i = 0; i < strideLimit; i += stride) { 1058 long lw = HBasePlatformDependent.getLong(obj1, o1 + (long) i); 1059 long rw = HBasePlatformDependent.getLong(obj2, o2 + (long) i); 1060 if (lw != rw) { 1061 if (!UnsafeAccess.LITTLE_ENDIAN) { 1062 return ((lw + Long.MIN_VALUE) < (rw + Long.MIN_VALUE)) ? -1 : 1; 1063 } 1064 1065 /* 1066 * We want to compare only the first index where left[index] != right[index]. This 1067 * corresponds to the least significant nonzero byte in lw ^ rw, since lw and rw are 1068 * little-endian. Long.numberOfTrailingZeros(diff) tells us the least significant nonzero 1069 * bit, and zeroing out the first three bits of L.nTZ gives us the shift to get that least 1070 * significant nonzero byte. This comparison logic is based on UnsignedBytes from guava v21 1071 */ 1072 int n = Long.numberOfTrailingZeros(lw ^ rw) & ~0x7; 1073 return ((int) ((lw >>> n) & 0xFF)) - ((int) ((rw >>> n) & 0xFF)); 1074 } 1075 } 1076 1077 // The epilogue to cover the last (minLength % stride) elements. 1078 for (; i < minLength; i++) { 1079 int il = (HBasePlatformDependent.getByte(obj1, o1 + i) & 0xFF); 1080 int ir = (HBasePlatformDependent.getByte(obj2, o2 + i) & 0xFF); 1081 if (il != ir) { 1082 return il - ir; 1083 } 1084 } 1085 return l1 - l2; 1086 } 1087 1088 static int findCommonPrefixUnsafe(Object left, long leftOffset, int leftLength, Object right, 1089 long rightOffset, int rightLength) { 1090 final int stride = 8; 1091 final int minLength = Math.min(leftLength, rightLength); 1092 int strideLimit = minLength & ~(stride - 1); 1093 int result = 0; 1094 int i; 1095 1096 for (i = 0; i < strideLimit; i += stride) { 1097 long lw = HBasePlatformDependent.getLong(left, leftOffset + (long) i); 1098 long rw = HBasePlatformDependent.getLong(right, rightOffset + (long) i); 1099 1100 if (lw != rw) { 1101 if (!UnsafeAccess.LITTLE_ENDIAN) { 1102 return result + (Long.numberOfLeadingZeros(lw ^ rw) / Bytes.SIZEOF_LONG); 1103 } else { 1104 return result + (Long.numberOfTrailingZeros(lw ^ rw) / Bytes.SIZEOF_LONG); 1105 } 1106 } else { 1107 result += Bytes.SIZEOF_LONG; 1108 } 1109 } 1110 1111 // The epilogue to cover the last (minLength % stride) elements. 1112 for (; i < minLength; i++) { 1113 byte il = HBasePlatformDependent.getByte(left, leftOffset + i); 1114 byte ir = HBasePlatformDependent.getByte(right, rightOffset + i); 1115 if (il != ir) { 1116 return result; 1117 } else { 1118 result++; 1119 } 1120 } 1121 1122 return result; 1123 } 1124 1125 /** 1126 * Reads a short value at the given buffer's offset. 1127 * @param buffer input byte buffer to read 1128 * @param offset input offset where short is 1129 * @return short value at offset 1130 */ 1131 public static short toShort(ByteBuffer buffer, int offset) { 1132 return ConverterHolder.BEST_CONVERTER.toShort(buffer, offset); 1133 } 1134 1135 /** 1136 * Reads an int value at the given buffer's current position. Also advances the buffer's position 1137 */ 1138 public static int toInt(ByteBuffer buffer) { 1139 return ConverterHolder.BEST_CONVERTER.toInt(buffer); 1140 } 1141 1142 /** 1143 * Reads an int value at the given buffer's offset. 1144 * @param buffer input byte buffer to read 1145 * @param offset input offset where int is 1146 * @return int value at offset 1147 */ 1148 public static int toInt(ByteBuffer buffer, int offset) { 1149 return ConverterHolder.BEST_CONVERTER.toInt(buffer, offset); 1150 } 1151 1152 /** 1153 * Converts a ByteBuffer to an int value 1154 * @param buf The ByteBuffer 1155 * @param offset Offset to int value 1156 * @param length Number of bytes used to store the int value. 1157 * @return the int value if there's not enough bytes left in the buffer after the given offset 1158 */ 1159 public static int readAsInt(ByteBuffer buf, int offset, final int length) { 1160 if (offset + length > buf.limit()) { 1161 throw new IllegalArgumentException("offset (" + offset + ") + length (" + length 1162 + ") exceed the" + " limit of the buffer: " + buf.limit()); 1163 } 1164 int n = 0; 1165 for (int i = offset; i < (offset + length); i++) { 1166 n <<= 8; 1167 n ^= toByte(buf, i) & 0xFF; 1168 } 1169 return n; 1170 } 1171 1172 /** 1173 * Reads a long value at the given buffer's offset. 1174 * @param buffer input byte buffer to read 1175 * @param offset input offset where Long is 1176 * @return long value at offset 1177 */ 1178 public static long toLong(ByteBuffer buffer, int offset) { 1179 return ConverterHolder.BEST_CONVERTER.toLong(buffer, offset); 1180 } 1181 1182 /** 1183 * Put an int value out to the given ByteBuffer's current position in big-endian format. This also 1184 * advances the position in buffer by int size. 1185 * @param buffer the ByteBuffer to write to 1186 * @param val int to write out 1187 */ 1188 public static void putInt(ByteBuffer buffer, int val) { 1189 ConverterHolder.BEST_CONVERTER.putInt(buffer, val); 1190 } 1191 1192 public static int putInt(ByteBuffer buffer, int index, int val) { 1193 return ConverterHolder.BEST_CONVERTER.putInt(buffer, index, val); 1194 } 1195 1196 /** 1197 * Reads a double value at the given buffer's offset. 1198 * @param buffer input byte buffer to read 1199 * @param offset offset where double is 1200 * @return double value at offset 1201 */ 1202 public static double toDouble(ByteBuffer buffer, int offset) { 1203 return Double.longBitsToDouble(toLong(buffer, offset)); 1204 } 1205 1206 /** 1207 * Reads a BigDecimal value at the given buffer's offset. 1208 * @param buffer input bytebuffer to read 1209 * @param offset input offset 1210 * @return BigDecimal value at offset 1211 */ 1212 public static BigDecimal toBigDecimal(ByteBuffer buffer, int offset, int length) { 1213 if (buffer == null || length < Bytes.SIZEOF_INT + 1 || (offset + length > buffer.limit())) { 1214 return null; 1215 } 1216 1217 int scale = toInt(buffer, offset); 1218 byte[] tcBytes = new byte[length - Bytes.SIZEOF_INT]; 1219 copyFromBufferToArray(tcBytes, buffer, offset + Bytes.SIZEOF_INT, 0, length - Bytes.SIZEOF_INT); 1220 return new BigDecimal(new BigInteger(tcBytes), scale); 1221 } 1222 1223 /** 1224 * Put a short value out to the given ByteBuffer's current position in big-endian format. This 1225 * also advances the position in buffer by short size. 1226 * @param buffer the ByteBuffer to write to 1227 * @param val short to write out 1228 */ 1229 public static void putShort(ByteBuffer buffer, short val) { 1230 ConverterHolder.BEST_CONVERTER.putShort(buffer, val); 1231 } 1232 1233 public static int putShort(ByteBuffer buffer, int index, short val) { 1234 return ConverterHolder.BEST_CONVERTER.putShort(buffer, index, val); 1235 } 1236 1237 public static int putAsShort(ByteBuffer buf, int index, int val) { 1238 buf.put(index + 1, (byte) val); 1239 val >>= 8; 1240 buf.put(index, (byte) val); 1241 return index + Bytes.SIZEOF_SHORT; 1242 } 1243 1244 /** 1245 * Put a long value out to the given ByteBuffer's current position in big-endian format. This also 1246 * advances the position in buffer by long size. 1247 * @param buffer the ByteBuffer to write to 1248 * @param val long to write out 1249 */ 1250 public static void putLong(ByteBuffer buffer, long val) { 1251 ConverterHolder.BEST_CONVERTER.putLong(buffer, val); 1252 } 1253 1254 public static int putLong(ByteBuffer buffer, int index, long val) { 1255 return ConverterHolder.BEST_CONVERTER.putLong(buffer, index, val); 1256 } 1257 1258 /** 1259 * Copies the bytes from given array's offset to length part into the given buffer. Puts the bytes 1260 * to buffer's current position. This also advances the position in the 'out' buffer by 'length' 1261 * @param out output bytebuffer to copy to 1262 * @param in input array to copy from 1263 * @param inOffset input offset to copy from 1264 * @param length the number of bytes to copy 1265 */ 1266 public static void copyFromArrayToBuffer(ByteBuffer out, byte[] in, int inOffset, int length) { 1267 if (out.hasArray()) { 1268 System.arraycopy(in, inOffset, out.array(), out.arrayOffset() + out.position(), length); 1269 // Move the position in out by length 1270 out.position(out.position() + length); 1271 } else if (UNSAFE_AVAIL) { 1272 UnsafeAccess.copy(in, inOffset, out, out.position(), length); 1273 // Move the position in out by length 1274 out.position(out.position() + length); 1275 } else { 1276 out.put(in, inOffset, length); 1277 } 1278 } 1279 1280 /** 1281 * Copies bytes from given array's offset to length part into the given buffer. Puts the bytes to 1282 * buffer's given position. This doesn't affect the position of buffer. 1283 * @param out output bytebuffer to copy to 1284 * @param outOffset output buffer offset 1285 * @param in input array to copy from 1286 * @param inOffset input offset to copy from 1287 * @param length the number of bytes to copy 1288 */ 1289 public static void copyFromArrayToBuffer(ByteBuffer out, int outOffset, byte[] in, int inOffset, 1290 int length) { 1291 if (out.hasArray()) { 1292 System.arraycopy(in, inOffset, out.array(), out.arrayOffset() + outOffset, length); 1293 } else if (UNSAFE_AVAIL) { 1294 UnsafeAccess.copy(in, inOffset, out, outOffset, length); 1295 } else { 1296 ByteBuffer outDup = out.duplicate(); 1297 outDup.position(outOffset); 1298 outDup.put(in, inOffset, length); 1299 } 1300 } 1301 1302 /** 1303 * Copies specified number of bytes from given offset of 'in' ByteBuffer to the array. This 1304 * doesn't affect the position of buffer. 1305 * @param out output array to copy input bytebuffer to 1306 * @param in input bytebuffer to copy from 1307 * @param sourceOffset offset of source bytebuffer 1308 * @param destinationOffset offset of destination array 1309 * @param length the number of bytes to copy 1310 */ 1311 public static void copyFromBufferToArray(byte[] out, ByteBuffer in, int sourceOffset, 1312 int destinationOffset, int length) { 1313 if (in.hasArray()) { 1314 System.arraycopy(in.array(), sourceOffset + in.arrayOffset(), out, destinationOffset, length); 1315 } else if (UNSAFE_AVAIL) { 1316 UnsafeAccess.copy(in, sourceOffset, out, destinationOffset, length); 1317 } else { 1318 ByteBuffer inDup = in.duplicate(); 1319 inDup.position(sourceOffset); 1320 inDup.get(out, destinationOffset, length); 1321 } 1322 } 1323 1324 /** 1325 * Similar to {@link Arrays#copyOfRange(byte[], int, int)} 1326 * @param original the buffer from which the copy has to happen 1327 * @param from the starting index 1328 * @param to the ending index 1329 * @return a byte[] created out of the copy 1330 */ 1331 public static byte[] copyOfRange(ByteBuffer original, int from, int to) { 1332 int newLength = to - from; 1333 if (newLength < 0) { 1334 throw new IllegalArgumentException(from + " > " + to); 1335 } 1336 byte[] copy = new byte[newLength]; 1337 ByteBufferUtils.copyFromBufferToArray(copy, original, from, 0, newLength); 1338 return copy; 1339 } 1340 1341 // For testing purpose 1342 public static String toStringBinary(final ByteBuffer b, int off, int len) { 1343 StringBuilder result = new StringBuilder(); 1344 // Just in case we are passed a 'len' that is > buffer length... 1345 if (off >= b.capacity()) { 1346 return result.toString(); 1347 } 1348 if (off + len > b.capacity()) { 1349 len = b.capacity() - off; 1350 } 1351 for (int i = off; i < off + len; ++i) { 1352 int ch = b.get(i) & 0xFF; 1353 if ( 1354 (ch >= '0' && ch <= '9') || (ch >= 'A' && ch <= 'Z') || (ch >= 'a' && ch <= 'z') 1355 || " `~!@#$%^&*()-_=+[]{}|;:'\",.<>/?".indexOf(ch) >= 0 1356 ) { 1357 result.append((char) ch); 1358 } else { 1359 result.append(String.format("\\x%02X", ch)); 1360 } 1361 } 1362 return result.toString(); 1363 } 1364 1365 public static String toStringBinary(final ByteBuffer b) { 1366 return toStringBinary(b, 0, b.capacity()); 1367 } 1368 1369 /** 1370 * Find index of passed delimiter. 1371 * @return Index of delimiter having started from start of <code>b</code> moving rightward. 1372 */ 1373 public static int searchDelimiterIndex(ByteBuffer b, int offset, final int length, 1374 final int delimiter) { 1375 for (int i = offset, n = offset + length; i < n; i++) { 1376 if (b.get(i) == delimiter) { 1377 return i; 1378 } 1379 } 1380 return -1; 1381 } 1382 1383 /** 1384 * Find index of passed delimiter walking from end of buffer backwards. 1385 * @return Index of delimiter 1386 */ 1387 public static int searchDelimiterIndexInReverse(ByteBuffer b, int offset, int length, 1388 int delimiter) { 1389 for (int i = offset + length - 1; i >= offset; i--) { 1390 if (b.get(i) == delimiter) { 1391 return i; 1392 } 1393 } 1394 return -1; 1395 } 1396}