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, 013 * software distributed under the License is distributed on an 014 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 015 * KIND, either express or implied. See the License for the 016 * specific language governing permissions and limitations 017 * under the License. 018 * 019 */ 020package org.apache.mina.core.buffer; 021 022import java.io.EOFException; 023import java.io.IOException; 024import java.io.InputStream; 025import java.io.ObjectInputStream; 026import java.io.ObjectOutputStream; 027import java.io.ObjectStreamClass; 028import java.io.OutputStream; 029import java.io.Serializable; 030import java.io.StreamCorruptedException; 031import java.nio.BufferOverflowException; 032import java.nio.BufferUnderflowException; 033import java.nio.ByteBuffer; 034import java.nio.ByteOrder; 035import java.nio.CharBuffer; 036import java.nio.DoubleBuffer; 037import java.nio.FloatBuffer; 038import java.nio.IntBuffer; 039import java.nio.LongBuffer; 040import java.nio.ShortBuffer; 041import java.nio.charset.CharacterCodingException; 042import java.nio.charset.CharsetDecoder; 043import java.nio.charset.CharsetEncoder; 044import java.nio.charset.CoderResult; 045import java.util.EnumSet; 046import java.util.Set; 047 048/** 049 * A base implementation of {@link IoBuffer}. This implementation 050 * assumes that {@link IoBuffer#buf()} always returns a correct NIO 051 * {@link ByteBuffer} instance. Most implementations could 052 * extend this class and implement their own buffer management mechanism. 053 * 054 * @author <a href="http://mina.apache.org">Apache MINA Project</a> 055 * @see IoBufferAllocator 056 */ 057public abstract class AbstractIoBuffer extends IoBuffer { 058 /** Tells if a buffer has been created from an existing buffer */ 059 private final boolean derived; 060 061 /** A flag set to true if the buffer can extend automatically */ 062 private boolean autoExpand; 063 064 /** A flag set to true if the buffer can shrink automatically */ 065 private boolean autoShrink; 066 067 /** Tells if a buffer can be expanded */ 068 private boolean recapacityAllowed = true; 069 070 /** The minimum number of bytes the IoBuffer can hold */ 071 private int minimumCapacity; 072 073 /** A mask for a byte */ 074 private static final long BYTE_MASK = 0xFFL; 075 076 /** A mask for a short */ 077 private static final long SHORT_MASK = 0xFFFFL; 078 079 /** A mask for an int */ 080 private static final long INT_MASK = 0xFFFFFFFFL; 081 082 /** 083 * We don't have any access to Buffer.markValue(), so we need to track it down, 084 * which will cause small extra overhead. 085 */ 086 private int mark = -1; 087 088 /** 089 * Creates a new parent buffer. 090 * 091 * @param allocator The allocator to use to create new buffers 092 * @param initialCapacity The initial buffer capacity when created 093 */ 094 protected AbstractIoBuffer(IoBufferAllocator allocator, int initialCapacity) { 095 setAllocator(allocator); 096 this.recapacityAllowed = true; 097 this.derived = false; 098 this.minimumCapacity = initialCapacity; 099 } 100 101 /** 102 * Creates a new derived buffer. A derived buffer uses an existing 103 * buffer properties - the allocator and capacity -. 104 * 105 * @param parent The buffer we get the properties from 106 */ 107 protected AbstractIoBuffer(AbstractIoBuffer parent) { 108 setAllocator(IoBuffer.getAllocator()); 109 this.recapacityAllowed = false; 110 this.derived = true; 111 this.minimumCapacity = parent.minimumCapacity; 112 } 113 114 /** 115 * {@inheritDoc} 116 */ 117 @Override 118 public final boolean isDirect() { 119 return buf().isDirect(); 120 } 121 122 /** 123 * {@inheritDoc} 124 */ 125 @Override 126 public final boolean isReadOnly() { 127 return buf().isReadOnly(); 128 } 129 130 /** 131 * Sets the underlying NIO buffer instance. 132 * 133 * @param newBuf The buffer to store within this IoBuffer 134 */ 135 protected abstract void buf(ByteBuffer newBuf); 136 137 /** 138 * {@inheritDoc} 139 */ 140 @Override 141 public final int minimumCapacity() { 142 return minimumCapacity; 143 } 144 145 /** 146 * {@inheritDoc} 147 */ 148 @Override 149 public final IoBuffer minimumCapacity(int minimumCapacity) { 150 if (minimumCapacity < 0) { 151 throw new IllegalArgumentException("minimumCapacity: " + minimumCapacity); 152 } 153 this.minimumCapacity = minimumCapacity; 154 return this; 155 } 156 157 /** 158 * {@inheritDoc} 159 */ 160 @Override 161 public final int capacity() { 162 return buf().capacity(); 163 } 164 165 /** 166 * {@inheritDoc} 167 */ 168 @Override 169 public final IoBuffer capacity(int newCapacity) { 170 if (!recapacityAllowed) { 171 throw new IllegalStateException("Derived buffers and their parent can't be expanded."); 172 } 173 174 // Allocate a new buffer and transfer all settings to it. 175 if (newCapacity > capacity()) { 176 // Expand: 177 //// Save the state. 178 int pos = position(); 179 int limit = limit(); 180 ByteOrder bo = order(); 181 182 //// Reallocate. 183 ByteBuffer oldBuf = buf(); 184 ByteBuffer newBuf = getAllocator().allocateNioBuffer(newCapacity, isDirect()); 185 oldBuf.clear(); 186 newBuf.put(oldBuf); 187 buf(newBuf); 188 189 //// Restore the state. 190 buf().limit(limit); 191 if (mark >= 0) { 192 buf().position(mark); 193 buf().mark(); 194 } 195 buf().position(pos); 196 buf().order(bo); 197 } 198 199 return this; 200 } 201 202 /** 203 * {@inheritDoc} 204 */ 205 @Override 206 public final boolean isAutoExpand() { 207 return autoExpand && recapacityAllowed; 208 } 209 210 /** 211 * {@inheritDoc} 212 */ 213 @Override 214 public final boolean isAutoShrink() { 215 return autoShrink && recapacityAllowed; 216 } 217 218 /** 219 * {@inheritDoc} 220 */ 221 @Override 222 public final boolean isDerived() { 223 return derived; 224 } 225 226 /** 227 * {@inheritDoc} 228 */ 229 @Override 230 public final IoBuffer setAutoExpand(boolean autoExpand) { 231 if (!recapacityAllowed) { 232 throw new IllegalStateException("Derived buffers and their parent can't be expanded."); 233 } 234 this.autoExpand = autoExpand; 235 return this; 236 } 237 238 /** 239 * {@inheritDoc} 240 */ 241 @Override 242 public final IoBuffer setAutoShrink(boolean autoShrink) { 243 if (!recapacityAllowed) { 244 throw new IllegalStateException("Derived buffers and their parent can't be shrinked."); 245 } 246 this.autoShrink = autoShrink; 247 return this; 248 } 249 250 /** 251 * {@inheritDoc} 252 */ 253 @Override 254 public final IoBuffer expand(int expectedRemaining) { 255 return expand(position(), expectedRemaining, false); 256 } 257 258 private IoBuffer expand(int expectedRemaining, boolean autoExpand) { 259 return expand(position(), expectedRemaining, autoExpand); 260 } 261 262 /** 263 * {@inheritDoc} 264 */ 265 @Override 266 public final IoBuffer expand(int pos, int expectedRemaining) { 267 return expand(pos, expectedRemaining, false); 268 } 269 270 private IoBuffer expand(int pos, int expectedRemaining, boolean autoExpand) { 271 if (!recapacityAllowed) { 272 throw new IllegalStateException("Derived buffers and their parent can't be expanded."); 273 } 274 275 int end = pos + expectedRemaining; 276 int newCapacity; 277 278 if (autoExpand) { 279 newCapacity = IoBuffer.normalizeCapacity(end); 280 } else { 281 newCapacity = end; 282 } 283 if (newCapacity > capacity()) { 284 // The buffer needs expansion. 285 capacity(newCapacity); 286 } 287 288 if (end > limit()) { 289 // We call limit() directly to prevent StackOverflowError 290 buf().limit(end); 291 } 292 return this; 293 } 294 295 /** 296 * {@inheritDoc} 297 */ 298 @Override 299 public final IoBuffer shrink() { 300 301 if (!recapacityAllowed) { 302 throw new IllegalStateException("Derived buffers and their parent can't be expanded."); 303 } 304 305 int position = position(); 306 int capacity = capacity(); 307 int limit = limit(); 308 309 if (capacity == limit) { 310 return this; 311 } 312 313 int newCapacity = capacity; 314 int minCapacity = Math.max(minimumCapacity, limit); 315 316 for (;;) { 317 if (newCapacity >>> 1 < minCapacity) { 318 break; 319 } 320 321 newCapacity >>>= 1; 322 323 if (minCapacity == 0) { 324 break; 325 } 326 } 327 328 newCapacity = Math.max(minCapacity, newCapacity); 329 330 if (newCapacity == capacity) { 331 return this; 332 } 333 334 // Shrink and compact: 335 //// Save the state. 336 ByteOrder bo = order(); 337 338 //// Reallocate. 339 ByteBuffer oldBuf = buf(); 340 ByteBuffer newBuf = getAllocator().allocateNioBuffer(newCapacity, isDirect()); 341 oldBuf.position(0); 342 oldBuf.limit(limit); 343 newBuf.put(oldBuf); 344 buf(newBuf); 345 346 //// Restore the state. 347 buf().position(position); 348 buf().limit(limit); 349 buf().order(bo); 350 mark = -1; 351 352 return this; 353 } 354 355 /** 356 * {@inheritDoc} 357 */ 358 @Override 359 public final int position() { 360 return buf().position(); 361 } 362 363 /** 364 * {@inheritDoc} 365 */ 366 @Override 367 public final IoBuffer position(int newPosition) { 368 autoExpand(newPosition, 0); 369 buf().position(newPosition); 370 371 if (mark > newPosition) { 372 mark = -1; 373 } 374 375 return this; 376 } 377 378 /** 379 * {@inheritDoc} 380 */ 381 @Override 382 public final int limit() { 383 return buf().limit(); 384 } 385 386 /** 387 * {@inheritDoc} 388 */ 389 @Override 390 public final IoBuffer limit(int newLimit) { 391 autoExpand(newLimit, 0); 392 buf().limit(newLimit); 393 if (mark > newLimit) { 394 mark = -1; 395 } 396 return this; 397 } 398 399 /** 400 * {@inheritDoc} 401 */ 402 @Override 403 public final IoBuffer mark() { 404 ByteBuffer byteBuffer = buf(); 405 byteBuffer.mark(); 406 mark = byteBuffer.position(); 407 408 return this; 409 } 410 411 /** 412 * {@inheritDoc} 413 */ 414 @Override 415 public final int markValue() { 416 return mark; 417 } 418 419 /** 420 * {@inheritDoc} 421 */ 422 @Override 423 public final IoBuffer reset() { 424 buf().reset(); 425 return this; 426 } 427 428 /** 429 * {@inheritDoc} 430 */ 431 @Override 432 public final IoBuffer clear() { 433 buf().clear(); 434 mark = -1; 435 return this; 436 } 437 438 /** 439 * {@inheritDoc} 440 */ 441 @Override 442 public final IoBuffer sweep() { 443 clear(); 444 return fillAndReset(remaining()); 445 } 446 447 /** 448 * {@inheritDoc} 449 */ 450 @Override 451 public final IoBuffer sweep(byte value) { 452 clear(); 453 return fillAndReset(value, remaining()); 454 } 455 456 /** 457 * {@inheritDoc} 458 */ 459 @Override 460 public final IoBuffer flip() { 461 buf().flip(); 462 mark = -1; 463 return this; 464 } 465 466 /** 467 * {@inheritDoc} 468 */ 469 @Override 470 public final IoBuffer rewind() { 471 buf().rewind(); 472 mark = -1; 473 return this; 474 } 475 476 /** 477 * {@inheritDoc} 478 */ 479 @Override 480 public final int remaining() { 481 ByteBuffer byteBuffer = buf(); 482 483 return byteBuffer.limit() - byteBuffer.position(); 484 } 485 486 /** 487 * {@inheritDoc} 488 */ 489 @Override 490 public final boolean hasRemaining() { 491 ByteBuffer byteBuffer = buf(); 492 493 return byteBuffer.limit() > byteBuffer.position(); 494 } 495 496 /** 497 * {@inheritDoc} 498 */ 499 @Override 500 public final byte get() { 501 return buf().get(); 502 } 503 504 /** 505 * {@inheritDoc} 506 */ 507 @Override 508 public final short getUnsigned() { 509 return (short) (get() & 0xff); 510 } 511 512 /** 513 * {@inheritDoc} 514 */ 515 @Override 516 public final IoBuffer put(byte b) { 517 autoExpand(1); 518 buf().put(b); 519 return this; 520 } 521 522 /** 523 * {@inheritDoc} 524 */ 525 public IoBuffer putUnsigned(byte value) { 526 autoExpand(1); 527 buf().put((byte) (value & 0xff)); 528 return this; 529 } 530 531 /** 532 * {@inheritDoc} 533 */ 534 public IoBuffer putUnsigned(int index, byte value) { 535 autoExpand(index, 1); 536 buf().put(index, (byte) (value & 0xff)); 537 return this; 538 } 539 540 /** 541 * {@inheritDoc} 542 */ 543 public IoBuffer putUnsigned(short value) { 544 autoExpand(1); 545 buf().put((byte) (value & 0x00ff)); 546 return this; 547 } 548 549 /** 550 * {@inheritDoc} 551 */ 552 public IoBuffer putUnsigned(int index, short value) { 553 autoExpand(index, 1); 554 buf().put(index, (byte) (value & 0x00ff)); 555 return this; 556 } 557 558 /** 559 * {@inheritDoc} 560 */ 561 public IoBuffer putUnsigned(int value) { 562 autoExpand(1); 563 buf().put((byte) (value & 0x000000ff)); 564 return this; 565 } 566 567 /** 568 * {@inheritDoc} 569 */ 570 public IoBuffer putUnsigned(int index, int value) { 571 autoExpand(index, 1); 572 buf().put(index, (byte) (value & 0x000000ff)); 573 return this; 574 } 575 576 /** 577 * {@inheritDoc} 578 */ 579 public IoBuffer putUnsigned(long value) { 580 autoExpand(1); 581 buf().put((byte) (value & 0x00000000000000ffL)); 582 return this; 583 } 584 585 /** 586 * {@inheritDoc} 587 */ 588 public IoBuffer putUnsigned(int index, long value) { 589 autoExpand(index, 1); 590 buf().put(index, (byte) (value & 0x00000000000000ffL)); 591 return this; 592 } 593 594 /** 595 * {@inheritDoc} 596 */ 597 @Override 598 public final byte get(int index) { 599 return buf().get(index); 600 } 601 602 /** 603 * {@inheritDoc} 604 */ 605 @Override 606 public final short getUnsigned(int index) { 607 return (short) (get(index) & 0xff); 608 } 609 610 /** 611 * {@inheritDoc} 612 */ 613 @Override 614 public final IoBuffer put(int index, byte b) { 615 autoExpand(index, 1); 616 buf().put(index, b); 617 return this; 618 } 619 620 /** 621 * {@inheritDoc} 622 */ 623 @Override 624 public final IoBuffer get(byte[] dst, int offset, int length) { 625 buf().get(dst, offset, length); 626 return this; 627 } 628 629 /** 630 * {@inheritDoc} 631 */ 632 @Override 633 public final IoBuffer put(ByteBuffer src) { 634 autoExpand(src.remaining()); 635 buf().put(src); 636 return this; 637 } 638 639 /** 640 * {@inheritDoc} 641 */ 642 @Override 643 public final IoBuffer put(byte[] src, int offset, int length) { 644 autoExpand(length); 645 buf().put(src, offset, length); 646 return this; 647 } 648 649 /** 650 * {@inheritDoc} 651 */ 652 @Override 653 public final IoBuffer compact() { 654 int remaining = remaining(); 655 int capacity = capacity(); 656 657 if (capacity == 0) { 658 return this; 659 } 660 661 if (isAutoShrink() && remaining <= capacity >>> 2 && capacity > minimumCapacity) { 662 int newCapacity = capacity; 663 int minCapacity = Math.max(minimumCapacity, remaining << 1); 664 for (;;) { 665 if (newCapacity >>> 1 < minCapacity) { 666 break; 667 } 668 newCapacity >>>= 1; 669 } 670 671 newCapacity = Math.max(minCapacity, newCapacity); 672 673 if (newCapacity == capacity) { 674 return this; 675 } 676 677 // Shrink and compact: 678 //// Save the state. 679 ByteOrder bo = order(); 680 681 //// Sanity check. 682 if (remaining > newCapacity) { 683 throw new IllegalStateException("The amount of the remaining bytes is greater than " 684 + "the new capacity."); 685 } 686 687 //// Reallocate. 688 ByteBuffer oldBuf = buf(); 689 ByteBuffer newBuf = getAllocator().allocateNioBuffer(newCapacity, isDirect()); 690 newBuf.put(oldBuf); 691 buf(newBuf); 692 693 //// Restore the state. 694 buf().order(bo); 695 } else { 696 buf().compact(); 697 } 698 mark = -1; 699 return this; 700 } 701 702 /** 703 * {@inheritDoc} 704 */ 705 @Override 706 public final ByteOrder order() { 707 return buf().order(); 708 } 709 710 /** 711 * {@inheritDoc} 712 */ 713 @Override 714 public final IoBuffer order(ByteOrder bo) { 715 buf().order(bo); 716 return this; 717 } 718 719 /** 720 * {@inheritDoc} 721 */ 722 @Override 723 public final char getChar() { 724 return buf().getChar(); 725 } 726 727 /** 728 * {@inheritDoc} 729 */ 730 @Override 731 public final IoBuffer putChar(char value) { 732 autoExpand(2); 733 buf().putChar(value); 734 return this; 735 } 736 737 /** 738 * {@inheritDoc} 739 */ 740 @Override 741 public final char getChar(int index) { 742 return buf().getChar(index); 743 } 744 745 /** 746 * {@inheritDoc} 747 */ 748 @Override 749 public final IoBuffer putChar(int index, char value) { 750 autoExpand(index, 2); 751 buf().putChar(index, value); 752 return this; 753 } 754 755 /** 756 * {@inheritDoc} 757 */ 758 @Override 759 public final CharBuffer asCharBuffer() { 760 return buf().asCharBuffer(); 761 } 762 763 /** 764 * {@inheritDoc} 765 */ 766 @Override 767 public final short getShort() { 768 return buf().getShort(); 769 } 770 771 /** 772 * {@inheritDoc} 773 */ 774 @Override 775 public final IoBuffer putShort(short value) { 776 autoExpand(2); 777 buf().putShort(value); 778 return this; 779 } 780 781 /** 782 * {@inheritDoc} 783 */ 784 @Override 785 public final short getShort(int index) { 786 return buf().getShort(index); 787 } 788 789 /** 790 * {@inheritDoc} 791 */ 792 @Override 793 public final IoBuffer putShort(int index, short value) { 794 autoExpand(index, 2); 795 buf().putShort(index, value); 796 return this; 797 } 798 799 /** 800 * {@inheritDoc} 801 */ 802 @Override 803 public final ShortBuffer asShortBuffer() { 804 return buf().asShortBuffer(); 805 } 806 807 /** 808 * {@inheritDoc} 809 */ 810 @Override 811 public final int getInt() { 812 return buf().getInt(); 813 } 814 815 /** 816 * {@inheritDoc} 817 */ 818 @Override 819 public final IoBuffer putInt(int value) { 820 autoExpand(4); 821 buf().putInt(value); 822 return this; 823 } 824 825 /** 826 * {@inheritDoc} 827 */ 828 @Override 829 public final IoBuffer putUnsignedInt(byte value) { 830 autoExpand(4); 831 buf().putInt((value & 0x00ff)); 832 return this; 833 } 834 835 /** 836 * {@inheritDoc} 837 */ 838 @Override 839 public final IoBuffer putUnsignedInt(int index, byte value) { 840 autoExpand(index, 4); 841 buf().putInt(index, (value & 0x00ff)); 842 return this; 843 } 844 845 /** 846 * {@inheritDoc} 847 */ 848 @Override 849 public final IoBuffer putUnsignedInt(short value) { 850 autoExpand(4); 851 buf().putInt((value & 0x0000ffff)); 852 return this; 853 } 854 855 /** 856 * {@inheritDoc} 857 */ 858 @Override 859 public final IoBuffer putUnsignedInt(int index, short value) { 860 autoExpand(index, 4); 861 buf().putInt(index, (value & 0x0000ffff)); 862 return this; 863 } 864 865 /** 866 * {@inheritDoc} 867 */ 868 @Override 869 public final IoBuffer putUnsignedInt(int value) { 870 autoExpand(4); 871 buf().putInt(value); 872 return this; 873 } 874 875 /** 876 * {@inheritDoc} 877 */ 878 @Override 879 public final IoBuffer putUnsignedInt(int index, int value) { 880 autoExpand(index, 4); 881 buf().putInt(index, value); 882 return this; 883 } 884 885 /** 886 * {@inheritDoc} 887 */ 888 @Override 889 public final IoBuffer putUnsignedInt(long value) { 890 autoExpand(4); 891 buf().putInt((int) (value & 0x00000000ffffffff)); 892 return this; 893 } 894 895 /** 896 * {@inheritDoc} 897 */ 898 @Override 899 public final IoBuffer putUnsignedInt(int index, long value) { 900 autoExpand(index, 4); 901 buf().putInt(index, (int) (value & 0x00000000ffffffffL)); 902 return this; 903 } 904 905 /** 906 * {@inheritDoc} 907 */ 908 @Override 909 public final IoBuffer putUnsignedShort(byte value) { 910 autoExpand(2); 911 buf().putShort((short) (value & 0x00ff)); 912 return this; 913 } 914 915 /** 916 * {@inheritDoc} 917 */ 918 @Override 919 public final IoBuffer putUnsignedShort(int index, byte value) { 920 autoExpand(index, 2); 921 buf().putShort(index, (short) (value & 0x00ff)); 922 return this; 923 } 924 925 /** 926 * {@inheritDoc} 927 */ 928 @Override 929 public final IoBuffer putUnsignedShort(short value) { 930 autoExpand(2); 931 buf().putShort(value); 932 return this; 933 } 934 935 /** 936 * {@inheritDoc} 937 */ 938 @Override 939 public final IoBuffer putUnsignedShort(int index, short value) { 940 autoExpand(index, 2); 941 buf().putShort(index, value); 942 return this; 943 } 944 945 /** 946 * {@inheritDoc} 947 */ 948 @Override 949 public final IoBuffer putUnsignedShort(int value) { 950 autoExpand(2); 951 buf().putShort((short) value); 952 return this; 953 } 954 955 /** 956 * {@inheritDoc} 957 */ 958 @Override 959 public final IoBuffer putUnsignedShort(int index, int value) { 960 autoExpand(index, 2); 961 buf().putShort(index, (short) value); 962 return this; 963 } 964 965 /** 966 * {@inheritDoc} 967 */ 968 @Override 969 public final IoBuffer putUnsignedShort(long value) { 970 autoExpand(2); 971 buf().putShort((short) (value)); 972 return this; 973 } 974 975 /** 976 * {@inheritDoc} 977 */ 978 @Override 979 public final IoBuffer putUnsignedShort(int index, long value) { 980 autoExpand(index, 2); 981 buf().putShort(index, (short) (value)); 982 return this; 983 } 984 985 /** 986 * {@inheritDoc} 987 */ 988 @Override 989 public final int getInt(int index) { 990 return buf().getInt(index); 991 } 992 993 /** 994 * {@inheritDoc} 995 */ 996 @Override 997 public final IoBuffer putInt(int index, int value) { 998 autoExpand(index, 4); 999 buf().putInt(index, value); 1000 return this; 1001 } 1002 1003 /** 1004 * {@inheritDoc} 1005 */ 1006 @Override 1007 public final IntBuffer asIntBuffer() { 1008 return buf().asIntBuffer(); 1009 } 1010 1011 /** 1012 * {@inheritDoc} 1013 */ 1014 @Override 1015 public final long getLong() { 1016 return buf().getLong(); 1017 } 1018 1019 /** 1020 * {@inheritDoc} 1021 */ 1022 @Override 1023 public final IoBuffer putLong(long value) { 1024 autoExpand(8); 1025 buf().putLong(value); 1026 return this; 1027 } 1028 1029 /** 1030 * {@inheritDoc} 1031 */ 1032 @Override 1033 public final long getLong(int index) { 1034 return buf().getLong(index); 1035 } 1036 1037 /** 1038 * {@inheritDoc} 1039 */ 1040 @Override 1041 public final IoBuffer putLong(int index, long value) { 1042 autoExpand(index, 8); 1043 buf().putLong(index, value); 1044 return this; 1045 } 1046 1047 /** 1048 * {@inheritDoc} 1049 */ 1050 @Override 1051 public final LongBuffer asLongBuffer() { 1052 return buf().asLongBuffer(); 1053 } 1054 1055 /** 1056 * {@inheritDoc} 1057 */ 1058 @Override 1059 public final float getFloat() { 1060 return buf().getFloat(); 1061 } 1062 1063 /** 1064 * {@inheritDoc} 1065 */ 1066 @Override 1067 public final IoBuffer putFloat(float value) { 1068 autoExpand(4); 1069 buf().putFloat(value); 1070 return this; 1071 } 1072 1073 /** 1074 * {@inheritDoc} 1075 */ 1076 @Override 1077 public final float getFloat(int index) { 1078 return buf().getFloat(index); 1079 } 1080 1081 /** 1082 * {@inheritDoc} 1083 */ 1084 @Override 1085 public final IoBuffer putFloat(int index, float value) { 1086 autoExpand(index, 4); 1087 buf().putFloat(index, value); 1088 return this; 1089 } 1090 1091 /** 1092 * {@inheritDoc} 1093 */ 1094 @Override 1095 public final FloatBuffer asFloatBuffer() { 1096 return buf().asFloatBuffer(); 1097 } 1098 1099 /** 1100 * {@inheritDoc} 1101 */ 1102 @Override 1103 public final double getDouble() { 1104 return buf().getDouble(); 1105 } 1106 1107 /** 1108 * {@inheritDoc} 1109 */ 1110 @Override 1111 public final IoBuffer putDouble(double value) { 1112 autoExpand(8); 1113 buf().putDouble(value); 1114 return this; 1115 } 1116 1117 /** 1118 * {@inheritDoc} 1119 */ 1120 @Override 1121 public final double getDouble(int index) { 1122 return buf().getDouble(index); 1123 } 1124 1125 /** 1126 * {@inheritDoc} 1127 */ 1128 @Override 1129 public final IoBuffer putDouble(int index, double value) { 1130 autoExpand(index, 8); 1131 buf().putDouble(index, value); 1132 return this; 1133 } 1134 1135 /** 1136 * {@inheritDoc} 1137 */ 1138 @Override 1139 public final DoubleBuffer asDoubleBuffer() { 1140 return buf().asDoubleBuffer(); 1141 } 1142 1143 /** 1144 * {@inheritDoc} 1145 */ 1146 @Override 1147 public final IoBuffer asReadOnlyBuffer() { 1148 recapacityAllowed = false; 1149 return asReadOnlyBuffer0(); 1150 } 1151 1152 /** 1153 * Implement this method to return the unexpandable read only version of 1154 * this buffer. 1155 * 1156 * @return the IoBoffer instance 1157 */ 1158 protected abstract IoBuffer asReadOnlyBuffer0(); 1159 1160 /** 1161 * {@inheritDoc} 1162 */ 1163 @Override 1164 public final IoBuffer duplicate() { 1165 recapacityAllowed = false; 1166 return duplicate0(); 1167 } 1168 1169 /** 1170 * Implement this method to return the unexpandable duplicate of this 1171 * buffer. 1172 * 1173 * @return the IoBoffer instance 1174 */ 1175 protected abstract IoBuffer duplicate0(); 1176 1177 /** 1178 * {@inheritDoc} 1179 */ 1180 @Override 1181 public final IoBuffer slice() { 1182 recapacityAllowed = false; 1183 return slice0(); 1184 } 1185 1186 /** 1187 * {@inheritDoc} 1188 */ 1189 @Override 1190 public final IoBuffer getSlice(int index, int length) { 1191 if (length < 0) { 1192 throw new IllegalArgumentException("length: " + length); 1193 } 1194 1195 int pos = position(); 1196 int limit = limit(); 1197 1198 if (index > limit) { 1199 throw new IllegalArgumentException("index: " + index); 1200 } 1201 1202 int endIndex = index + length; 1203 1204 if (endIndex > limit) { 1205 throw new IndexOutOfBoundsException("index + length (" + endIndex + ") is greater " + "than limit (" 1206 + limit + ")."); 1207 } 1208 1209 clear(); 1210 limit(endIndex); 1211 position(index); 1212 1213 IoBuffer slice = slice(); 1214 limit(limit); 1215 position(pos); 1216 1217 return slice; 1218 } 1219 1220 /** 1221 * {@inheritDoc} 1222 */ 1223 @Override 1224 public final IoBuffer getSlice(int length) { 1225 if (length < 0) { 1226 throw new IllegalArgumentException("length: " + length); 1227 } 1228 int pos = position(); 1229 int limit = limit(); 1230 int nextPos = pos + length; 1231 if (limit < nextPos) { 1232 throw new IndexOutOfBoundsException("position + length (" + nextPos + ") is greater " + "than limit (" 1233 + limit + ")."); 1234 } 1235 1236 limit(pos + length); 1237 IoBuffer slice = slice(); 1238 position(nextPos); 1239 limit(limit); 1240 return slice; 1241 } 1242 1243 /** 1244 * Implement this method to return the unexpandable slice of this 1245 * buffer. 1246 * 1247 * @return the IoBoffer instance 1248 */ 1249 protected abstract IoBuffer slice0(); 1250 1251 /** 1252 * {@inheritDoc} 1253 */ 1254 @Override 1255 public int hashCode() { 1256 int h = 1; 1257 int p = position(); 1258 for (int i = limit() - 1; i >= p; i--) { 1259 h = 31 * h + get(i); 1260 } 1261 return h; 1262 } 1263 1264 /** 1265 * {@inheritDoc} 1266 */ 1267 @Override 1268 public boolean equals(Object o) { 1269 if (!(o instanceof IoBuffer)) { 1270 return false; 1271 } 1272 1273 IoBuffer that = (IoBuffer) o; 1274 if (this.remaining() != that.remaining()) { 1275 return false; 1276 } 1277 1278 int p = this.position(); 1279 for (int i = this.limit() - 1, j = that.limit() - 1; i >= p; i--, j--) { 1280 byte v1 = this.get(i); 1281 byte v2 = that.get(j); 1282 if (v1 != v2) { 1283 return false; 1284 } 1285 } 1286 return true; 1287 } 1288 1289 /** 1290 * {@inheritDoc} 1291 */ 1292 public int compareTo(IoBuffer that) { 1293 int n = this.position() + Math.min(this.remaining(), that.remaining()); 1294 for (int i = this.position(), j = that.position(); i < n; i++, j++) { 1295 byte v1 = this.get(i); 1296 byte v2 = that.get(j); 1297 if (v1 == v2) { 1298 continue; 1299 } 1300 if (v1 < v2) { 1301 return -1; 1302 } 1303 1304 return +1; 1305 } 1306 return this.remaining() - that.remaining(); 1307 } 1308 1309 /** 1310 * {@inheritDoc} 1311 */ 1312 @Override 1313 public String toString() { 1314 StringBuilder buf = new StringBuilder(); 1315 if (isDirect()) { 1316 buf.append("DirectBuffer"); 1317 } else { 1318 buf.append("HeapBuffer"); 1319 } 1320 buf.append("[pos="); 1321 buf.append(position()); 1322 buf.append(" lim="); 1323 buf.append(limit()); 1324 buf.append(" cap="); 1325 buf.append(capacity()); 1326 buf.append(": "); 1327 buf.append(getHexDump(16)); 1328 buf.append(']'); 1329 return buf.toString(); 1330 } 1331 1332 /** 1333 * {@inheritDoc} 1334 */ 1335 @Override 1336 public IoBuffer get(byte[] dst) { 1337 return get(dst, 0, dst.length); 1338 } 1339 1340 /** 1341 * {@inheritDoc} 1342 */ 1343 @Override 1344 public IoBuffer put(IoBuffer src) { 1345 return put(src.buf()); 1346 } 1347 1348 /** 1349 * {@inheritDoc} 1350 */ 1351 @Override 1352 public IoBuffer put(byte[] src) { 1353 return put(src, 0, src.length); 1354 } 1355 1356 /** 1357 * {@inheritDoc} 1358 */ 1359 @Override 1360 public int getUnsignedShort() { 1361 return getShort() & 0xffff; 1362 } 1363 1364 /** 1365 * {@inheritDoc} 1366 */ 1367 @Override 1368 public int getUnsignedShort(int index) { 1369 return getShort(index) & 0xffff; 1370 } 1371 1372 /** 1373 * {@inheritDoc} 1374 */ 1375 @Override 1376 public long getUnsignedInt() { 1377 return getInt() & 0xffffffffL; 1378 } 1379 1380 /** 1381 * {@inheritDoc} 1382 */ 1383 @Override 1384 public int getMediumInt() { 1385 byte b1 = get(); 1386 byte b2 = get(); 1387 byte b3 = get(); 1388 if (ByteOrder.BIG_ENDIAN.equals(order())) { 1389 return getMediumInt(b1, b2, b3); 1390 } 1391 1392 return getMediumInt(b3, b2, b1); 1393 } 1394 1395 /** 1396 * {@inheritDoc} 1397 */ 1398 @Override 1399 public int getUnsignedMediumInt() { 1400 int b1 = getUnsigned(); 1401 int b2 = getUnsigned(); 1402 int b3 = getUnsigned(); 1403 if (ByteOrder.BIG_ENDIAN.equals(order())) { 1404 return b1 << 16 | b2 << 8 | b3; 1405 } 1406 1407 return b3 << 16 | b2 << 8 | b1; 1408 } 1409 1410 /** 1411 * {@inheritDoc} 1412 */ 1413 @Override 1414 public int getMediumInt(int index) { 1415 byte b1 = get(index); 1416 byte b2 = get(index + 1); 1417 byte b3 = get(index + 2); 1418 if (ByteOrder.BIG_ENDIAN.equals(order())) { 1419 return getMediumInt(b1, b2, b3); 1420 } 1421 1422 return getMediumInt(b3, b2, b1); 1423 } 1424 1425 /** 1426 * {@inheritDoc} 1427 */ 1428 @Override 1429 public int getUnsignedMediumInt(int index) { 1430 int b1 = getUnsigned(index); 1431 int b2 = getUnsigned(index + 1); 1432 int b3 = getUnsigned(index + 2); 1433 1434 if (ByteOrder.BIG_ENDIAN.equals(order())) { 1435 return b1 << 16 | b2 << 8 | b3; 1436 } 1437 1438 return b3 << 16 | b2 << 8 | b1; 1439 } 1440 1441 /** 1442 * {@inheritDoc} 1443 */ 1444 private int getMediumInt(byte b1, byte b2, byte b3) { 1445 int ret = b1 << 16 & 0xff0000 | b2 << 8 & 0xff00 | b3 & 0xff; 1446 // Check to see if the medium int is negative (high bit in b1 set) 1447 if ((b1 & 0x80) == 0x80) { 1448 // Make the the whole int negative 1449 ret |= 0xff000000; 1450 } 1451 return ret; 1452 } 1453 1454 /** 1455 * {@inheritDoc} 1456 */ 1457 @Override 1458 public IoBuffer putMediumInt(int value) { 1459 byte b1 = (byte) (value >> 16); 1460 byte b2 = (byte) (value >> 8); 1461 byte b3 = (byte) value; 1462 1463 if (ByteOrder.BIG_ENDIAN.equals(order())) { 1464 put(b1).put(b2).put(b3); 1465 } else { 1466 put(b3).put(b2).put(b1); 1467 } 1468 1469 return this; 1470 } 1471 1472 /** 1473 * {@inheritDoc} 1474 */ 1475 @Override 1476 public IoBuffer putMediumInt(int index, int value) { 1477 byte b1 = (byte) (value >> 16); 1478 byte b2 = (byte) (value >> 8); 1479 byte b3 = (byte) value; 1480 1481 if (ByteOrder.BIG_ENDIAN.equals(order())) { 1482 put(index, b1).put(index + 1, b2).put(index + 2, b3); 1483 } else { 1484 put(index, b3).put(index + 1, b2).put(index + 2, b1); 1485 } 1486 1487 return this; 1488 } 1489 1490 /** 1491 * {@inheritDoc} 1492 */ 1493 @Override 1494 public long getUnsignedInt(int index) { 1495 return getInt(index) & 0xffffffffL; 1496 } 1497 1498 /** 1499 * {@inheritDoc} 1500 */ 1501 @Override 1502 public InputStream asInputStream() { 1503 return new InputStream() { 1504 @Override 1505 public int available() { 1506 return AbstractIoBuffer.this.remaining(); 1507 } 1508 1509 @Override 1510 public synchronized void mark(int readlimit) { 1511 AbstractIoBuffer.this.mark(); 1512 } 1513 1514 @Override 1515 public boolean markSupported() { 1516 return true; 1517 } 1518 1519 @Override 1520 public int read() { 1521 if (AbstractIoBuffer.this.hasRemaining()) { 1522 return AbstractIoBuffer.this.get() & 0xff; 1523 } 1524 1525 return -1; 1526 } 1527 1528 @Override 1529 public int read(byte[] b, int off, int len) { 1530 int remaining = AbstractIoBuffer.this.remaining(); 1531 if (remaining > 0) { 1532 int readBytes = Math.min(remaining, len); 1533 AbstractIoBuffer.this.get(b, off, readBytes); 1534 return readBytes; 1535 } 1536 1537 return -1; 1538 } 1539 1540 @Override 1541 public synchronized void reset() { 1542 AbstractIoBuffer.this.reset(); 1543 } 1544 1545 @Override 1546 public long skip(long n) { 1547 int bytes; 1548 if (n > Integer.MAX_VALUE) { 1549 bytes = AbstractIoBuffer.this.remaining(); 1550 } else { 1551 bytes = Math.min(AbstractIoBuffer.this.remaining(), (int) n); 1552 } 1553 AbstractIoBuffer.this.skip(bytes); 1554 return bytes; 1555 } 1556 }; 1557 } 1558 1559 /** 1560 * {@inheritDoc} 1561 */ 1562 @Override 1563 public OutputStream asOutputStream() { 1564 return new OutputStream() { 1565 @Override 1566 public void write(byte[] b, int off, int len) { 1567 AbstractIoBuffer.this.put(b, off, len); 1568 } 1569 1570 @Override 1571 public void write(int b) { 1572 AbstractIoBuffer.this.put((byte) b); 1573 } 1574 }; 1575 } 1576 1577 /** 1578 * {@inheritDoc} 1579 */ 1580 @Override 1581 public String getHexDump() { 1582 return this.getHexDump(Integer.MAX_VALUE); 1583 } 1584 1585 /** 1586 * {@inheritDoc} 1587 */ 1588 @Override 1589 public String getHexDump(int lengthLimit) { 1590 return IoBufferHexDumper.getHexdump(this, lengthLimit); 1591 } 1592 1593 /** 1594 * {@inheritDoc} 1595 */ 1596 @Override 1597 public String getString(CharsetDecoder decoder) throws CharacterCodingException { 1598 if (!hasRemaining()) { 1599 return ""; 1600 } 1601 1602 boolean utf16 = decoder.charset().name().startsWith("UTF-16"); 1603 1604 int oldPos = position(); 1605 int oldLimit = limit(); 1606 int end = -1; 1607 int newPos; 1608 1609 if (!utf16) { 1610 end = indexOf((byte) 0x00); 1611 if (end < 0) { 1612 newPos = end = oldLimit; 1613 } else { 1614 newPos = end + 1; 1615 } 1616 } else { 1617 int i = oldPos; 1618 for (;;) { 1619 boolean wasZero = get(i) == 0; 1620 i++; 1621 1622 if (i >= oldLimit) { 1623 break; 1624 } 1625 1626 if (get(i) != 0) { 1627 i++; 1628 if (i >= oldLimit) { 1629 break; 1630 } 1631 1632 continue; 1633 } 1634 1635 if (wasZero) { 1636 end = i - 1; 1637 break; 1638 } 1639 } 1640 1641 if (end < 0) { 1642 newPos = end = oldPos + (oldLimit - oldPos & 0xFFFFFFFE); 1643 } else { 1644 if (end + 2 <= oldLimit) { 1645 newPos = end + 2; 1646 } else { 1647 newPos = end; 1648 } 1649 } 1650 } 1651 1652 if (oldPos == end) { 1653 position(newPos); 1654 return ""; 1655 } 1656 1657 limit(end); 1658 decoder.reset(); 1659 1660 int expectedLength = (int) (remaining() * decoder.averageCharsPerByte()) + 1; 1661 CharBuffer out = CharBuffer.allocate(expectedLength); 1662 for (;;) { 1663 CoderResult cr; 1664 if (hasRemaining()) { 1665 cr = decoder.decode(buf(), out, true); 1666 } else { 1667 cr = decoder.flush(out); 1668 } 1669 1670 if (cr.isUnderflow()) { 1671 break; 1672 } 1673 1674 if (cr.isOverflow()) { 1675 CharBuffer o = CharBuffer.allocate(out.capacity() + expectedLength); 1676 out.flip(); 1677 o.put(out); 1678 out = o; 1679 continue; 1680 } 1681 1682 if (cr.isError()) { 1683 // Revert the buffer back to the previous state. 1684 limit(oldLimit); 1685 position(oldPos); 1686 cr.throwException(); 1687 } 1688 } 1689 1690 limit(oldLimit); 1691 position(newPos); 1692 return out.flip().toString(); 1693 } 1694 1695 /** 1696 * {@inheritDoc} 1697 */ 1698 @Override 1699 public String getString(int fieldSize, CharsetDecoder decoder) throws CharacterCodingException { 1700 checkFieldSize(fieldSize); 1701 1702 if (fieldSize == 0) { 1703 return ""; 1704 } 1705 1706 if (!hasRemaining()) { 1707 return ""; 1708 } 1709 1710 boolean utf16 = decoder.charset().name().startsWith("UTF-16"); 1711 1712 if (utf16 && (fieldSize & 1) != 0) { 1713 throw new IllegalArgumentException("fieldSize is not even."); 1714 } 1715 1716 int oldPos = position(); 1717 int oldLimit = limit(); 1718 int end = oldPos + fieldSize; 1719 1720 if (oldLimit < end) { 1721 throw new BufferUnderflowException(); 1722 } 1723 1724 int i; 1725 1726 if (!utf16) { 1727 for (i = oldPos; i < end; i++) { 1728 if (get(i) == 0) { 1729 break; 1730 } 1731 } 1732 1733 if (i == end) { 1734 limit(end); 1735 } else { 1736 limit(i); 1737 } 1738 } else { 1739 for (i = oldPos; i < end; i += 2) { 1740 if (get(i) == 0 && get(i + 1) == 0) { 1741 break; 1742 } 1743 } 1744 1745 if (i == end) { 1746 limit(end); 1747 } else { 1748 limit(i); 1749 } 1750 } 1751 1752 if (!hasRemaining()) { 1753 limit(oldLimit); 1754 position(end); 1755 return ""; 1756 } 1757 decoder.reset(); 1758 1759 int expectedLength = (int) (remaining() * decoder.averageCharsPerByte()) + 1; 1760 CharBuffer out = CharBuffer.allocate(expectedLength); 1761 for (;;) { 1762 CoderResult cr; 1763 if (hasRemaining()) { 1764 cr = decoder.decode(buf(), out, true); 1765 } else { 1766 cr = decoder.flush(out); 1767 } 1768 1769 if (cr.isUnderflow()) { 1770 break; 1771 } 1772 1773 if (cr.isOverflow()) { 1774 CharBuffer o = CharBuffer.allocate(out.capacity() + expectedLength); 1775 out.flip(); 1776 o.put(out); 1777 out = o; 1778 continue; 1779 } 1780 1781 if (cr.isError()) { 1782 // Revert the buffer back to the previous state. 1783 limit(oldLimit); 1784 position(oldPos); 1785 cr.throwException(); 1786 } 1787 } 1788 1789 limit(oldLimit); 1790 position(end); 1791 return out.flip().toString(); 1792 } 1793 1794 /** 1795 * {@inheritDoc} 1796 */ 1797 @Override 1798 public IoBuffer putString(CharSequence val, CharsetEncoder encoder) throws CharacterCodingException { 1799 if (val.length() == 0) { 1800 return this; 1801 } 1802 1803 CharBuffer in = CharBuffer.wrap(val); 1804 encoder.reset(); 1805 1806 int expandedState = 0; 1807 1808 for (;;) { 1809 CoderResult cr; 1810 if (in.hasRemaining()) { 1811 cr = encoder.encode(in, buf(), true); 1812 } else { 1813 cr = encoder.flush(buf()); 1814 } 1815 1816 if (cr.isUnderflow()) { 1817 break; 1818 } 1819 if (cr.isOverflow()) { 1820 if (isAutoExpand()) { 1821 switch (expandedState) { 1822 case 0: 1823 autoExpand((int) Math.ceil(in.remaining() * encoder.averageBytesPerChar())); 1824 expandedState++; 1825 break; 1826 case 1: 1827 autoExpand((int) Math.ceil(in.remaining() * encoder.maxBytesPerChar())); 1828 expandedState++; 1829 break; 1830 default: 1831 throw new RuntimeException("Expanded by " 1832 + (int) Math.ceil(in.remaining() * encoder.maxBytesPerChar()) 1833 + " but that wasn't enough for '" + val + "'"); 1834 } 1835 continue; 1836 } 1837 } else { 1838 expandedState = 0; 1839 } 1840 cr.throwException(); 1841 } 1842 return this; 1843 } 1844 1845 /** 1846 * {@inheritDoc} 1847 */ 1848 @Override 1849 public IoBuffer putString(CharSequence val, int fieldSize, CharsetEncoder encoder) throws CharacterCodingException { 1850 checkFieldSize(fieldSize); 1851 1852 if (fieldSize == 0) { 1853 return this; 1854 } 1855 1856 autoExpand(fieldSize); 1857 1858 boolean utf16 = encoder.charset().name().startsWith("UTF-16"); 1859 1860 if (utf16 && (fieldSize & 1) != 0) { 1861 throw new IllegalArgumentException("fieldSize is not even."); 1862 } 1863 1864 int oldLimit = limit(); 1865 int end = position() + fieldSize; 1866 1867 if (oldLimit < end) { 1868 throw new BufferOverflowException(); 1869 } 1870 1871 if (val.length() == 0) { 1872 if (!utf16) { 1873 put((byte) 0x00); 1874 } else { 1875 put((byte) 0x00); 1876 put((byte) 0x00); 1877 } 1878 position(end); 1879 return this; 1880 } 1881 1882 CharBuffer in = CharBuffer.wrap(val); 1883 limit(end); 1884 encoder.reset(); 1885 1886 for (;;) { 1887 CoderResult cr; 1888 if (in.hasRemaining()) { 1889 cr = encoder.encode(in, buf(), true); 1890 } else { 1891 cr = encoder.flush(buf()); 1892 } 1893 1894 if (cr.isUnderflow() || cr.isOverflow()) { 1895 break; 1896 } 1897 cr.throwException(); 1898 } 1899 1900 limit(oldLimit); 1901 1902 if (position() < end) { 1903 if (!utf16) { 1904 put((byte) 0x00); 1905 } else { 1906 put((byte) 0x00); 1907 put((byte) 0x00); 1908 } 1909 } 1910 1911 position(end); 1912 return this; 1913 } 1914 1915 /** 1916 * {@inheritDoc} 1917 */ 1918 @Override 1919 public String getPrefixedString(CharsetDecoder decoder) throws CharacterCodingException { 1920 return getPrefixedString(2, decoder); 1921 } 1922 1923 /** 1924 * Reads a string which has a length field before the actual 1925 * encoded string, using the specified <code>decoder</code> and returns it. 1926 * 1927 * @param prefixLength the length of the length field (1, 2, or 4) 1928 * @param decoder the decoder to use for decoding the string 1929 * @return the prefixed string 1930 * @throws CharacterCodingException when decoding fails 1931 * @throws BufferUnderflowException when there is not enough data available 1932 */ 1933 @Override 1934 public String getPrefixedString(int prefixLength, CharsetDecoder decoder) throws CharacterCodingException { 1935 if (!prefixedDataAvailable(prefixLength)) { 1936 throw new BufferUnderflowException(); 1937 } 1938 1939 int fieldSize = 0; 1940 1941 switch (prefixLength) { 1942 case 1: 1943 fieldSize = getUnsigned(); 1944 break; 1945 case 2: 1946 fieldSize = getUnsignedShort(); 1947 break; 1948 case 4: 1949 fieldSize = getInt(); 1950 break; 1951 } 1952 1953 if (fieldSize == 0) { 1954 return ""; 1955 } 1956 1957 boolean utf16 = decoder.charset().name().startsWith("UTF-16"); 1958 1959 if (utf16 && (fieldSize & 1) != 0) { 1960 throw new BufferDataException("fieldSize is not even for a UTF-16 string."); 1961 } 1962 1963 int oldLimit = limit(); 1964 int end = position() + fieldSize; 1965 1966 if (oldLimit < end) { 1967 throw new BufferUnderflowException(); 1968 } 1969 1970 limit(end); 1971 decoder.reset(); 1972 1973 int expectedLength = (int) (remaining() * decoder.averageCharsPerByte()) + 1; 1974 CharBuffer out = CharBuffer.allocate(expectedLength); 1975 for (;;) { 1976 CoderResult cr; 1977 if (hasRemaining()) { 1978 cr = decoder.decode(buf(), out, true); 1979 } else { 1980 cr = decoder.flush(out); 1981 } 1982 1983 if (cr.isUnderflow()) { 1984 break; 1985 } 1986 1987 if (cr.isOverflow()) { 1988 CharBuffer o = CharBuffer.allocate(out.capacity() + expectedLength); 1989 out.flip(); 1990 o.put(out); 1991 out = o; 1992 continue; 1993 } 1994 1995 cr.throwException(); 1996 } 1997 1998 limit(oldLimit); 1999 position(end); 2000 return out.flip().toString(); 2001 } 2002 2003 /** 2004 * {@inheritDoc} 2005 */ 2006 @Override 2007 public IoBuffer putPrefixedString(CharSequence in, CharsetEncoder encoder) throws CharacterCodingException { 2008 return putPrefixedString(in, 2, 0, encoder); 2009 } 2010 2011 /** 2012 * {@inheritDoc} 2013 */ 2014 @Override 2015 public IoBuffer putPrefixedString(CharSequence in, int prefixLength, CharsetEncoder encoder) 2016 throws CharacterCodingException { 2017 return putPrefixedString(in, prefixLength, 0, encoder); 2018 } 2019 2020 /** 2021 * {@inheritDoc} 2022 */ 2023 @Override 2024 public IoBuffer putPrefixedString(CharSequence in, int prefixLength, int padding, CharsetEncoder encoder) 2025 throws CharacterCodingException { 2026 return putPrefixedString(in, prefixLength, padding, (byte) 0, encoder); 2027 } 2028 2029 /** 2030 * {@inheritDoc} 2031 */ 2032 @Override 2033 public IoBuffer putPrefixedString(CharSequence val, int prefixLength, int padding, byte padValue, 2034 CharsetEncoder encoder) throws CharacterCodingException { 2035 int maxLength; 2036 switch (prefixLength) { 2037 case 1: 2038 maxLength = 255; 2039 break; 2040 case 2: 2041 maxLength = 65535; 2042 break; 2043 case 4: 2044 maxLength = Integer.MAX_VALUE; 2045 break; 2046 default: 2047 throw new IllegalArgumentException("prefixLength: " + prefixLength); 2048 } 2049 2050 if (val.length() > maxLength) { 2051 throw new IllegalArgumentException("The specified string is too long."); 2052 } 2053 if (val.length() == 0) { 2054 switch (prefixLength) { 2055 case 1: 2056 put((byte) 0); 2057 break; 2058 case 2: 2059 putShort((short) 0); 2060 break; 2061 case 4: 2062 putInt(0); 2063 break; 2064 } 2065 return this; 2066 } 2067 2068 int padMask; 2069 switch (padding) { 2070 case 0: 2071 case 1: 2072 padMask = 0; 2073 break; 2074 case 2: 2075 padMask = 1; 2076 break; 2077 case 4: 2078 padMask = 3; 2079 break; 2080 default: 2081 throw new IllegalArgumentException("padding: " + padding); 2082 } 2083 2084 CharBuffer in = CharBuffer.wrap(val); 2085 skip(prefixLength); // make a room for the length field 2086 int oldPos = position(); 2087 encoder.reset(); 2088 2089 int expandedState = 0; 2090 2091 for (;;) { 2092 CoderResult cr; 2093 if (in.hasRemaining()) { 2094 cr = encoder.encode(in, buf(), true); 2095 } else { 2096 cr = encoder.flush(buf()); 2097 } 2098 2099 if (position() - oldPos > maxLength) { 2100 throw new IllegalArgumentException("The specified string is too long."); 2101 } 2102 2103 if (cr.isUnderflow()) { 2104 break; 2105 } 2106 if (cr.isOverflow()) { 2107 if (isAutoExpand()) { 2108 switch (expandedState) { 2109 case 0: 2110 autoExpand((int) Math.ceil(in.remaining() * encoder.averageBytesPerChar())); 2111 expandedState++; 2112 break; 2113 case 1: 2114 autoExpand((int) Math.ceil(in.remaining() * encoder.maxBytesPerChar())); 2115 expandedState++; 2116 break; 2117 default: 2118 throw new RuntimeException("Expanded by " 2119 + (int) Math.ceil(in.remaining() * encoder.maxBytesPerChar()) 2120 + " but that wasn't enough for '" + val + "'"); 2121 } 2122 continue; 2123 } 2124 } else { 2125 expandedState = 0; 2126 } 2127 cr.throwException(); 2128 } 2129 2130 // Write the length field 2131 fill(padValue, padding - (position() - oldPos & padMask)); 2132 int length = position() - oldPos; 2133 switch (prefixLength) { 2134 case 1: 2135 put(oldPos - 1, (byte) length); 2136 break; 2137 case 2: 2138 putShort(oldPos - 2, (short) length); 2139 break; 2140 case 4: 2141 putInt(oldPos - 4, length); 2142 break; 2143 } 2144 return this; 2145 } 2146 2147 /** 2148 * {@inheritDoc} 2149 */ 2150 @Override 2151 public Object getObject() throws ClassNotFoundException { 2152 return getObject(Thread.currentThread().getContextClassLoader()); 2153 } 2154 2155 /** 2156 * {@inheritDoc} 2157 */ 2158 @Override 2159 public Object getObject(final ClassLoader classLoader) throws ClassNotFoundException { 2160 if (!prefixedDataAvailable(4)) { 2161 throw new BufferUnderflowException(); 2162 } 2163 2164 int length = getInt(); 2165 if (length <= 4) { 2166 throw new BufferDataException("Object length should be greater than 4: " + length); 2167 } 2168 2169 int oldLimit = limit(); 2170 limit(position() + length); 2171 ObjectInputStream in = null; 2172 2173 try { 2174 in = new ObjectInputStream(asInputStream()) { 2175 @Override 2176 protected ObjectStreamClass readClassDescriptor() throws IOException, ClassNotFoundException { 2177 int type = read(); 2178 if (type < 0) { 2179 throw new EOFException(); 2180 } 2181 switch (type) { 2182 case 0: // NON-Serializable class or Primitive types 2183 return super.readClassDescriptor(); 2184 case 1: // Serializable class 2185 String className = readUTF(); 2186 Class<?> clazz = Class.forName(className, true, classLoader); 2187 return ObjectStreamClass.lookup(clazz); 2188 default: 2189 throw new StreamCorruptedException("Unexpected class descriptor type: " + type); 2190 } 2191 } 2192 2193 @Override 2194 protected Class<?> resolveClass(ObjectStreamClass desc) throws IOException, ClassNotFoundException { 2195 Class<?> clazz = desc.forClass(); 2196 2197 if (clazz == null) { 2198 String name = desc.getName(); 2199 try { 2200 return Class.forName(name, false, classLoader); 2201 } catch (ClassNotFoundException ex) { 2202 return super.resolveClass(desc); 2203 } 2204 } else { 2205 return clazz; 2206 } 2207 } 2208 }; 2209 return in.readObject(); 2210 } catch (IOException e) { 2211 throw new BufferDataException(e); 2212 } finally { 2213 try { 2214 if (in != null) { 2215 in.close(); 2216 } 2217 } catch (IOException ioe) { 2218 // Nothing to do 2219 } 2220 2221 limit(oldLimit); 2222 } 2223 } 2224 2225 /** 2226 * {@inheritDoc} 2227 */ 2228 @Override 2229 public IoBuffer putObject(Object o) { 2230 int oldPos = position(); 2231 skip(4); // Make a room for the length field. 2232 ObjectOutputStream out = null; 2233 2234 try { 2235 out = new ObjectOutputStream(asOutputStream()) { 2236 @Override 2237 protected void writeClassDescriptor(ObjectStreamClass desc) throws IOException { 2238 Class<?> clazz = desc.forClass(); 2239 2240 if (clazz.isArray() || clazz.isPrimitive() || !Serializable.class.isAssignableFrom(clazz)) { 2241 write(0); 2242 super.writeClassDescriptor(desc); 2243 } else { 2244 // Serializable class 2245 write(1); 2246 writeUTF(desc.getName()); 2247 } 2248 } 2249 }; 2250 out.writeObject(o); 2251 out.flush(); 2252 } catch (IOException e) { 2253 throw new BufferDataException(e); 2254 } finally { 2255 try { 2256 if (out != null) { 2257 out.close(); 2258 } 2259 } catch (IOException ioe) { 2260 // Nothing to do 2261 } 2262 } 2263 2264 // Fill the length field 2265 int newPos = position(); 2266 position(oldPos); 2267 putInt(newPos - oldPos - 4); 2268 position(newPos); 2269 return this; 2270 } 2271 2272 /** 2273 * {@inheritDoc} 2274 */ 2275 @Override 2276 public boolean prefixedDataAvailable(int prefixLength) { 2277 return prefixedDataAvailable(prefixLength, Integer.MAX_VALUE); 2278 } 2279 2280 /** 2281 * {@inheritDoc} 2282 */ 2283 @Override 2284 public boolean prefixedDataAvailable(int prefixLength, int maxDataLength) { 2285 if (remaining() < prefixLength) { 2286 return false; 2287 } 2288 2289 int dataLength; 2290 switch (prefixLength) { 2291 case 1: 2292 dataLength = getUnsigned(position()); 2293 break; 2294 case 2: 2295 dataLength = getUnsignedShort(position()); 2296 break; 2297 case 4: 2298 dataLength = getInt(position()); 2299 break; 2300 default: 2301 throw new IllegalArgumentException("prefixLength: " + prefixLength); 2302 } 2303 2304 if (dataLength < 0 || dataLength > maxDataLength) { 2305 throw new BufferDataException("dataLength: " + dataLength); 2306 } 2307 2308 return remaining() - prefixLength >= dataLength; 2309 } 2310 2311 /** 2312 * {@inheritDoc} 2313 */ 2314 @Override 2315 public int indexOf(byte b) { 2316 if (hasArray()) { 2317 int arrayOffset = arrayOffset(); 2318 int beginPos = arrayOffset + position(); 2319 int limit = arrayOffset + limit(); 2320 byte[] array = array(); 2321 2322 for (int i = beginPos; i < limit; i++) { 2323 if (array[i] == b) { 2324 return i - arrayOffset; 2325 } 2326 } 2327 } else { 2328 int beginPos = position(); 2329 int limit = limit(); 2330 2331 for (int i = beginPos; i < limit; i++) { 2332 if (get(i) == b) { 2333 return i; 2334 } 2335 } 2336 } 2337 2338 return -1; 2339 } 2340 2341 /** 2342 * {@inheritDoc} 2343 */ 2344 @Override 2345 public IoBuffer skip(int size) { 2346 autoExpand(size); 2347 return position(position() + size); 2348 } 2349 2350 /** 2351 * {@inheritDoc} 2352 */ 2353 @Override 2354 public IoBuffer fill(byte value, int size) { 2355 autoExpand(size); 2356 int q = size >>> 3; 2357 int r = size & 7; 2358 2359 if (q > 0) { 2360 int intValue = value & 0x000000FF | ( value << 8 ) & 0x0000FF00 | ( value << 16 ) & 0x00FF0000 | value << 24; 2361 long longValue = intValue & 0x00000000FFFFFFFFL | (long)intValue << 32; 2362 2363 for (int i = q; i > 0; i--) { 2364 putLong(longValue); 2365 } 2366 } 2367 2368 q = r >>> 2; 2369 r = r & 3; 2370 2371 if (q > 0) { 2372 int intValue = value & 0x000000FF | ( value << 8 ) & 0x0000FF00 | ( value << 16 ) & 0x00FF0000 | value << 24; 2373 putInt(intValue); 2374 } 2375 2376 q = r >> 1; 2377 r = r & 1; 2378 2379 if (q > 0) { 2380 short shortValue = (short) (value & 0x000FF | value << 8); 2381 putShort(shortValue); 2382 } 2383 2384 if (r > 0) { 2385 put(value); 2386 } 2387 2388 return this; 2389 } 2390 2391 /** 2392 * {@inheritDoc} 2393 */ 2394 @Override 2395 public IoBuffer fillAndReset(byte value, int size) { 2396 autoExpand(size); 2397 int pos = position(); 2398 try { 2399 fill(value, size); 2400 } finally { 2401 position(pos); 2402 } 2403 return this; 2404 } 2405 2406 /** 2407 * {@inheritDoc} 2408 */ 2409 @Override 2410 public IoBuffer fill(int size) { 2411 autoExpand(size); 2412 int q = size >>> 3; 2413 int r = size & 7; 2414 2415 for (int i = q; i > 0; i--) { 2416 putLong(0L); 2417 } 2418 2419 q = r >>> 2; 2420 r = r & 3; 2421 2422 if (q > 0) { 2423 putInt(0); 2424 } 2425 2426 q = r >> 1; 2427 r = r & 1; 2428 2429 if (q > 0) { 2430 putShort((short) 0); 2431 } 2432 2433 if (r > 0) { 2434 put((byte) 0); 2435 } 2436 2437 return this; 2438 } 2439 2440 /** 2441 * {@inheritDoc} 2442 */ 2443 @Override 2444 public IoBuffer fillAndReset(int size) { 2445 autoExpand(size); 2446 int pos = position(); 2447 try { 2448 fill(size); 2449 } finally { 2450 position(pos); 2451 } 2452 2453 return this; 2454 } 2455 2456 /** 2457 * {@inheritDoc} 2458 */ 2459 @Override 2460 public <E extends Enum<E>> E getEnum(Class<E> enumClass) { 2461 return toEnum(enumClass, getUnsigned()); 2462 } 2463 2464 /** 2465 * {@inheritDoc} 2466 */ 2467 @Override 2468 public <E extends Enum<E>> E getEnum(int index, Class<E> enumClass) { 2469 return toEnum(enumClass, getUnsigned(index)); 2470 } 2471 2472 /** 2473 * {@inheritDoc} 2474 */ 2475 @Override 2476 public <E extends Enum<E>> E getEnumShort(Class<E> enumClass) { 2477 return toEnum(enumClass, getUnsignedShort()); 2478 } 2479 2480 /** 2481 * {@inheritDoc} 2482 */ 2483 @Override 2484 public <E extends Enum<E>> E getEnumShort(int index, Class<E> enumClass) { 2485 return toEnum(enumClass, getUnsignedShort(index)); 2486 } 2487 2488 /** 2489 * {@inheritDoc} 2490 */ 2491 @Override 2492 public <E extends Enum<E>> E getEnumInt(Class<E> enumClass) { 2493 return toEnum(enumClass, getInt()); 2494 } 2495 2496 /** 2497 * {@inheritDoc} 2498 */ 2499 public <E extends Enum<E>> E getEnumInt(int index, Class<E> enumClass) { 2500 return toEnum(enumClass, getInt(index)); 2501 } 2502 2503 /** 2504 * {@inheritDoc} 2505 */ 2506 @Override 2507 public IoBuffer putEnum(Enum<?> e) { 2508 if (e.ordinal() > BYTE_MASK) { 2509 throw new IllegalArgumentException(enumConversionErrorMessage(e, "byte")); 2510 } 2511 return put((byte) e.ordinal()); 2512 } 2513 2514 /** 2515 * {@inheritDoc} 2516 */ 2517 @Override 2518 public IoBuffer putEnum(int index, Enum<?> e) { 2519 if (e.ordinal() > BYTE_MASK) { 2520 throw new IllegalArgumentException(enumConversionErrorMessage(e, "byte")); 2521 } 2522 return put(index, (byte) e.ordinal()); 2523 } 2524 2525 /** 2526 * {@inheritDoc} 2527 */ 2528 @Override 2529 public IoBuffer putEnumShort(Enum<?> e) { 2530 if (e.ordinal() > SHORT_MASK) { 2531 throw new IllegalArgumentException(enumConversionErrorMessage(e, "short")); 2532 } 2533 return putShort((short) e.ordinal()); 2534 } 2535 2536 /** 2537 * {@inheritDoc} 2538 */ 2539 @Override 2540 public IoBuffer putEnumShort(int index, Enum<?> e) { 2541 if (e.ordinal() > SHORT_MASK) { 2542 throw new IllegalArgumentException(enumConversionErrorMessage(e, "short")); 2543 } 2544 return putShort(index, (short) e.ordinal()); 2545 } 2546 2547 /** 2548 * {@inheritDoc} 2549 */ 2550 @Override 2551 public IoBuffer putEnumInt(Enum<?> e) { 2552 return putInt(e.ordinal()); 2553 } 2554 2555 /** 2556 * {@inheritDoc} 2557 */ 2558 @Override 2559 public IoBuffer putEnumInt(int index, Enum<?> e) { 2560 return putInt(index, e.ordinal()); 2561 } 2562 2563 private <E> E toEnum(Class<E> enumClass, int i) { 2564 E[] enumConstants = enumClass.getEnumConstants(); 2565 if (i > enumConstants.length) { 2566 throw new IndexOutOfBoundsException(String.format( 2567 "%d is too large of an ordinal to convert to the enum %s", i, enumClass.getName())); 2568 } 2569 return enumConstants[i]; 2570 } 2571 2572 private String enumConversionErrorMessage(Enum<?> e, String type) { 2573 return String.format("%s.%s has an ordinal value too large for a %s", e.getClass().getName(), e.name(), type); 2574 } 2575 2576 /** 2577 * {@inheritDoc} 2578 */ 2579 @Override 2580 public <E extends Enum<E>> EnumSet<E> getEnumSet(Class<E> enumClass) { 2581 return toEnumSet(enumClass, get() & BYTE_MASK); 2582 } 2583 2584 /** 2585 * {@inheritDoc} 2586 */ 2587 @Override 2588 public <E extends Enum<E>> EnumSet<E> getEnumSet(int index, Class<E> enumClass) { 2589 return toEnumSet(enumClass, get(index) & BYTE_MASK); 2590 } 2591 2592 /** 2593 * {@inheritDoc} 2594 */ 2595 @Override 2596 public <E extends Enum<E>> EnumSet<E> getEnumSetShort(Class<E> enumClass) { 2597 return toEnumSet(enumClass, getShort() & SHORT_MASK); 2598 } 2599 2600 /** 2601 * {@inheritDoc} 2602 */ 2603 @Override 2604 public <E extends Enum<E>> EnumSet<E> getEnumSetShort(int index, Class<E> enumClass) { 2605 return toEnumSet(enumClass, getShort(index) & SHORT_MASK); 2606 } 2607 2608 /** 2609 * {@inheritDoc} 2610 */ 2611 @Override 2612 public <E extends Enum<E>> EnumSet<E> getEnumSetInt(Class<E> enumClass) { 2613 return toEnumSet(enumClass, getInt() & INT_MASK); 2614 } 2615 2616 /** 2617 * {@inheritDoc} 2618 */ 2619 @Override 2620 public <E extends Enum<E>> EnumSet<E> getEnumSetInt(int index, Class<E> enumClass) { 2621 return toEnumSet(enumClass, getInt(index) & INT_MASK); 2622 } 2623 2624 /** 2625 * {@inheritDoc} 2626 */ 2627 @Override 2628 public <E extends Enum<E>> EnumSet<E> getEnumSetLong(Class<E> enumClass) { 2629 return toEnumSet(enumClass, getLong()); 2630 } 2631 2632 /** 2633 * {@inheritDoc} 2634 */ 2635 @Override 2636 public <E extends Enum<E>> EnumSet<E> getEnumSetLong(int index, Class<E> enumClass) { 2637 return toEnumSet(enumClass, getLong(index)); 2638 } 2639 2640 private <E extends Enum<E>> EnumSet<E> toEnumSet(Class<E> clazz, long vector) { 2641 EnumSet<E> set = EnumSet.noneOf(clazz); 2642 long mask = 1; 2643 for (E e : clazz.getEnumConstants()) { 2644 if ((mask & vector) == mask) { 2645 set.add(e); 2646 } 2647 mask <<= 1; 2648 } 2649 return set; 2650 } 2651 2652 /** 2653 * {@inheritDoc} 2654 */ 2655 @Override 2656 public <E extends Enum<E>> IoBuffer putEnumSet(Set<E> set) { 2657 long vector = toLong(set); 2658 if ((vector & ~BYTE_MASK) != 0) { 2659 throw new IllegalArgumentException("The enum set is too large to fit in a byte: " + set); 2660 } 2661 return put((byte) vector); 2662 } 2663 2664 /** 2665 * {@inheritDoc} 2666 */ 2667 @Override 2668 public <E extends Enum<E>> IoBuffer putEnumSet(int index, Set<E> set) { 2669 long vector = toLong(set); 2670 if ((vector & ~BYTE_MASK) != 0) { 2671 throw new IllegalArgumentException("The enum set is too large to fit in a byte: " + set); 2672 } 2673 return put(index, (byte) vector); 2674 } 2675 2676 /** 2677 * {@inheritDoc} 2678 */ 2679 @Override 2680 public <E extends Enum<E>> IoBuffer putEnumSetShort(Set<E> set) { 2681 long vector = toLong(set); 2682 if ((vector & ~SHORT_MASK) != 0) { 2683 throw new IllegalArgumentException("The enum set is too large to fit in a short: " + set); 2684 } 2685 return putShort((short) vector); 2686 } 2687 2688 /** 2689 * {@inheritDoc} 2690 */ 2691 @Override 2692 public <E extends Enum<E>> IoBuffer putEnumSetShort(int index, Set<E> set) { 2693 long vector = toLong(set); 2694 if ((vector & ~SHORT_MASK) != 0) { 2695 throw new IllegalArgumentException("The enum set is too large to fit in a short: " + set); 2696 } 2697 return putShort(index, (short) vector); 2698 } 2699 2700 /** 2701 * {@inheritDoc} 2702 */ 2703 @Override 2704 public <E extends Enum<E>> IoBuffer putEnumSetInt(Set<E> set) { 2705 long vector = toLong(set); 2706 if ((vector & ~INT_MASK) != 0) { 2707 throw new IllegalArgumentException("The enum set is too large to fit in an int: " + set); 2708 } 2709 return putInt((int) vector); 2710 } 2711 2712 /** 2713 * {@inheritDoc} 2714 */ 2715 @Override 2716 public <E extends Enum<E>> IoBuffer putEnumSetInt(int index, Set<E> set) { 2717 long vector = toLong(set); 2718 if ((vector & ~INT_MASK) != 0) { 2719 throw new IllegalArgumentException("The enum set is too large to fit in an int: " + set); 2720 } 2721 return putInt(index, (int) vector); 2722 } 2723 2724 /** 2725 * {@inheritDoc} 2726 */ 2727 @Override 2728 public <E extends Enum<E>> IoBuffer putEnumSetLong(Set<E> set) { 2729 return putLong(toLong(set)); 2730 } 2731 2732 /** 2733 * {@inheritDoc} 2734 */ 2735 @Override 2736 public <E extends Enum<E>> IoBuffer putEnumSetLong(int index, Set<E> set) { 2737 return putLong(index, toLong(set)); 2738 } 2739 2740 private <E extends Enum<E>> long toLong(Set<E> set) { 2741 long vector = 0; 2742 for (E e : set) { 2743 if (e.ordinal() >= Long.SIZE) { 2744 throw new IllegalArgumentException("The enum set is too large to fit in a bit vector: " + set); 2745 } 2746 vector |= 1L << e.ordinal(); 2747 } 2748 return vector; 2749 } 2750 2751 /** 2752 * This method forwards the call to {@link #expand(int)} only when 2753 * <tt>autoExpand</tt> property is <tt>true</tt>. 2754 */ 2755 private IoBuffer autoExpand(int expectedRemaining) { 2756 if (isAutoExpand()) { 2757 expand(expectedRemaining, true); 2758 } 2759 return this; 2760 } 2761 2762 /** 2763 * This method forwards the call to {@link #expand(int)} only when 2764 * <tt>autoExpand</tt> property is <tt>true</tt>. 2765 */ 2766 private IoBuffer autoExpand(int pos, int expectedRemaining) { 2767 if (isAutoExpand()) { 2768 expand(pos, expectedRemaining, true); 2769 } 2770 return this; 2771 } 2772 2773 private static void checkFieldSize(int fieldSize) { 2774 if (fieldSize < 0) { 2775 throw new IllegalArgumentException("fieldSize cannot be negative: " + fieldSize); 2776 } 2777 } 2778}