1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20 package org.apache.mina.common;
21
22 import java.io.EOFException;
23 import java.io.IOException;
24 import java.io.InputStream;
25 import java.io.ObjectInputStream;
26 import java.io.ObjectOutputStream;
27 import java.io.ObjectStreamClass;
28 import java.io.OutputStream;
29 import java.io.StreamCorruptedException;
30 import java.nio.BufferOverflowException;
31 import java.nio.BufferUnderflowException;
32 import java.nio.ByteBuffer;
33 import java.nio.ByteOrder;
34 import java.nio.CharBuffer;
35 import java.nio.DoubleBuffer;
36 import java.nio.FloatBuffer;
37 import java.nio.IntBuffer;
38 import java.nio.LongBuffer;
39 import java.nio.ShortBuffer;
40 import java.nio.charset.CharacterCodingException;
41 import java.nio.charset.CharsetDecoder;
42 import java.nio.charset.CharsetEncoder;
43 import java.nio.charset.CoderResult;
44 import java.util.EnumSet;
45 import java.util.Set;
46
47
48
49
50
51
52
53
54
55
56
57
58 public abstract class AbstractIoBuffer extends IoBuffer {
59
60 private final IoBufferAllocator allocator;
61 private final boolean derived;
62 private boolean autoExpand;
63 private boolean autoShrink;
64 private boolean recapacityAllowed = true;
65 private int minimumCapacity;
66
67
68
69
70
71 private int mark = -1;
72
73
74
75
76 protected AbstractIoBuffer(
77 IoBufferAllocator allocator, int initialCapacity) {
78 this.allocator = allocator;
79 this.recapacityAllowed = true;
80 this.derived = false;
81 this.minimumCapacity = initialCapacity;
82 }
83
84
85
86
87 protected AbstractIoBuffer(AbstractIoBuffer parent) {
88 this.allocator = parent.allocator;
89 this.recapacityAllowed = false;
90 this.derived = true;
91 this.minimumCapacity = parent.minimumCapacity;
92 }
93
94 @Override
95 public final boolean isDirect() {
96 return buf().isDirect();
97 }
98
99 @Override
100 public final boolean isReadOnly() {
101 return buf().isReadOnly();
102 }
103
104
105
106
107 protected abstract void buf(ByteBuffer newBuf);
108
109 @Override
110 public final int minimumCapacity() {
111 return minimumCapacity;
112 }
113
114 @Override
115 public final IoBuffer minimumCapacity(int minimumCapacity) {
116 if (minimumCapacity < 0) {
117 throw new IllegalArgumentException(
118 "minimumCapacity: " + minimumCapacity);
119 }
120 this.minimumCapacity = minimumCapacity;
121 return this;
122 }
123
124 @Override
125 public final int capacity() {
126 return buf().capacity();
127 }
128
129 @Override
130 public final IoBuffer capacity(int newCapacity) {
131 if (!recapacityAllowed) {
132 throw new IllegalStateException(
133 "Derived buffers and their parent can't be expanded.");
134 }
135
136
137 if (newCapacity > capacity()) {
138
139
140 int pos = position();
141 int limit = limit();
142 ByteOrder bo = order();
143
144
145 ByteBuffer oldBuf = buf();
146 ByteBuffer newBuf =
147 allocator.allocateNioBuffer(newCapacity, isDirect());
148 oldBuf.clear();
149 newBuf.put(oldBuf);
150 buf(newBuf);
151
152
153 buf().limit(limit);
154 if (mark >= 0) {
155 buf().position(mark);
156 buf().mark();
157 }
158 buf().position(pos);
159 buf().order(bo);
160 }
161
162 return this;
163 }
164
165 @Override
166 public final boolean isAutoExpand() {
167 return autoExpand && recapacityAllowed;
168 }
169
170 @Override
171 public final boolean isAutoShrink() {
172 return autoShrink && recapacityAllowed;
173 }
174
175 @Override
176 public final boolean isDerived() {
177 return derived;
178 }
179
180 @Override
181 public final IoBuffer setAutoExpand(boolean autoExpand) {
182 if (!recapacityAllowed) {
183 throw new IllegalStateException(
184 "Derived buffers and their parent can't be expanded.");
185 }
186 this.autoExpand = autoExpand;
187 return this;
188 }
189
190 @Override
191 public final IoBuffer setAutoShrink(boolean autoShrink) {
192 if (!recapacityAllowed) {
193 throw new IllegalStateException(
194 "Derived buffers and their parent can't be shrinked.");
195 }
196 this.autoShrink = autoShrink;
197 return this;
198 }
199
200 @Override
201 public final IoBuffer expand(int expectedRemaining) {
202 return expand(position(), expectedRemaining);
203 }
204
205 @Override
206 public final IoBuffer expand(int pos, int expectedRemaining) {
207 if (!recapacityAllowed) {
208 throw new IllegalStateException(
209 "Derived buffers and their parent can't be expanded.");
210 }
211
212 int end = pos + expectedRemaining;
213 if (end > capacity()) {
214
215 capacity(end);
216 }
217
218 if (end > limit()) {
219
220 buf().limit(end);
221 }
222 return this;
223 }
224
225 @Override
226 public final IoBuffer shrink() {
227
228 if (!recapacityAllowed) {
229 throw new IllegalStateException(
230 "Derived buffers and their parent can't be expanded.");
231 }
232
233 int position = position();
234 int capacity = capacity();
235 int limit = limit();
236 if (capacity == limit) {
237 return this;
238 }
239
240 int newCapacity = capacity;
241 int minCapacity = Math.max(minimumCapacity, limit);
242 for (;;) {
243 if (newCapacity >>> 1 < minCapacity) {
244 break;
245 }
246 newCapacity >>>= 1;
247 }
248
249 newCapacity = Math.max(minCapacity, newCapacity);
250
251 if (newCapacity == capacity) {
252 return this;
253 }
254
255
256
257 ByteOrder bo = order();
258
259
260 ByteBuffer oldBuf = buf();
261 ByteBuffer newBuf =
262 allocator.allocateNioBuffer(newCapacity, isDirect());
263 oldBuf.position(0);
264 oldBuf.limit(limit);
265 newBuf.put(oldBuf);
266 buf(newBuf);
267
268
269 buf().position(position);
270 buf().limit(limit);
271 buf().order(bo);
272 mark = -1;
273
274 return this;
275 }
276
277 @Override
278 public final int position() {
279 return buf().position();
280 }
281
282 @Override
283 public final IoBuffer position(int newPosition) {
284 autoExpand(newPosition, 0);
285 buf().position(newPosition);
286 if (mark > newPosition) {
287 mark = -1;
288 }
289 return this;
290 }
291
292 @Override
293 public final int limit() {
294 return buf().limit();
295 }
296
297 @Override
298 public final IoBuffer limit(int newLimit) {
299 autoExpand(newLimit, 0);
300 buf().limit(newLimit);
301 if (mark > newLimit) {
302 mark = -1;
303 }
304 return this;
305 }
306
307 @Override
308 public final IoBuffer mark() {
309 buf().mark();
310 mark = position();
311 return this;
312 }
313
314 @Override
315 public final int markValue() {
316 return mark;
317 }
318
319 @Override
320 public final IoBuffer reset() {
321 buf().reset();
322 return this;
323 }
324
325 @Override
326 public final IoBuffer clear() {
327 buf().clear();
328 mark = -1;
329 return this;
330 }
331
332 @Override
333 public final IoBuffer sweep() {
334 clear();
335 return fillAndReset(remaining());
336 }
337
338 @Override
339 public final IoBuffer sweep(byte value) {
340 clear();
341 return fillAndReset(value, remaining());
342 }
343
344 @Override
345 public final IoBuffer flip() {
346 buf().flip();
347 mark = -1;
348 return this;
349 }
350
351 @Override
352 public final IoBuffer rewind() {
353 buf().rewind();
354 mark = -1;
355 return this;
356 }
357
358 @Override
359 public final int remaining() {
360 return limit() - position();
361 }
362
363 @Override
364 public final boolean hasRemaining() {
365 return limit() > position();
366 }
367
368 @Override
369 public final byte get() {
370 return buf().get();
371 }
372
373 @Override
374 public final short getUnsigned() {
375 return (short) (get() & 0xff);
376 }
377
378 @Override
379 public final IoBuffer put(byte b) {
380 autoExpand(1);
381 buf().put(b);
382 return this;
383 }
384
385 @Override
386 public final byte get(int index) {
387 return buf().get(index);
388 }
389
390 @Override
391 public final short getUnsigned(int index) {
392 return (short) (get(index) & 0xff);
393 }
394
395 @Override
396 public final IoBuffer put(int index, byte b) {
397 autoExpand(index, 1);
398 buf().put(index, b);
399 return this;
400 }
401
402 @Override
403 public final IoBuffer get(byte[] dst, int offset, int length) {
404 buf().get(dst, offset, length);
405 return this;
406 }
407
408 @Override
409 public final IoBuffer put(ByteBuffer src) {
410 autoExpand(src.remaining());
411 buf().put(src);
412 return this;
413 }
414
415 @Override
416 public final IoBuffer put(byte[] src, int offset, int length) {
417 autoExpand(length);
418 buf().put(src, offset, length);
419 return this;
420 }
421
422 @Override
423 public final IoBuffer compact() {
424 int remaining = remaining();
425 int capacity = capacity();
426
427 if (capacity == 0) {
428 return this;
429 }
430
431 if (isAutoShrink() && remaining <= capacity >>> 2 && capacity > minimumCapacity) {
432 int newCapacity = capacity;
433 int minCapacity = Math.max(minimumCapacity, remaining << 1);
434 for (;;) {
435 if (newCapacity >>> 1 < minCapacity) {
436 break;
437 }
438 newCapacity >>>= 1;
439 }
440
441 newCapacity = Math.max(minCapacity, newCapacity);
442
443 if (newCapacity == capacity) {
444 return this;
445 }
446
447
448
449 ByteOrder bo = order();
450
451
452 if (remaining > newCapacity) {
453 throw new IllegalStateException(
454 "The amount of the remaining bytes is greater than " +
455 "the new capacity.");
456 }
457
458
459 ByteBuffer oldBuf = buf();
460 ByteBuffer newBuf =
461 allocator.allocateNioBuffer(newCapacity, isDirect());
462 newBuf.put(oldBuf);
463 buf(newBuf);
464
465
466 buf().order(bo);
467 } else {
468 buf().compact();
469 }
470 mark = -1;
471 return this;
472 }
473
474 @Override
475 public final ByteOrder order() {
476 return buf().order();
477 }
478
479 @Override
480 public final IoBuffer order(ByteOrder bo) {
481 buf().order(bo);
482 return this;
483 }
484
485 @Override
486 public final char getChar() {
487 return buf().getChar();
488 }
489
490 @Override
491 public final IoBuffer putChar(char value) {
492 autoExpand(2);
493 buf().putChar(value);
494 return this;
495 }
496
497 @Override
498 public final char getChar(int index) {
499 return buf().getChar(index);
500 }
501
502 @Override
503 public final IoBuffer putChar(int index, char value) {
504 autoExpand(index, 2);
505 buf().putChar(index, value);
506 return this;
507 }
508
509 @Override
510 public final CharBuffer asCharBuffer() {
511 return buf().asCharBuffer();
512 }
513
514 @Override
515 public final short getShort() {
516 return buf().getShort();
517 }
518
519 @Override
520 public final IoBuffer putShort(short value) {
521 autoExpand(2);
522 buf().putShort(value);
523 return this;
524 }
525
526 @Override
527 public final short getShort(int index) {
528 return buf().getShort(index);
529 }
530
531 @Override
532 public final IoBuffer putShort(int index, short value) {
533 autoExpand(index, 2);
534 buf().putShort(index, value);
535 return this;
536 }
537
538 @Override
539 public final ShortBuffer asShortBuffer() {
540 return buf().asShortBuffer();
541 }
542
543 @Override
544 public final int getInt() {
545 return buf().getInt();
546 }
547
548 @Override
549 public final IoBuffer putInt(int value) {
550 autoExpand(4);
551 buf().putInt(value);
552 return this;
553 }
554
555 @Override
556 public final int getInt(int index) {
557 return buf().getInt(index);
558 }
559
560 @Override
561 public final IoBuffer putInt(int index, int value) {
562 autoExpand(index, 4);
563 buf().putInt(index, value);
564 return this;
565 }
566
567 @Override
568 public final IntBuffer asIntBuffer() {
569 return buf().asIntBuffer();
570 }
571
572 @Override
573 public final long getLong() {
574 return buf().getLong();
575 }
576
577 @Override
578 public final IoBuffer putLong(long value) {
579 autoExpand(8);
580 buf().putLong(value);
581 return this;
582 }
583
584 @Override
585 public final long getLong(int index) {
586 return buf().getLong(index);
587 }
588
589 @Override
590 public final IoBuffer putLong(int index, long value) {
591 autoExpand(index, 8);
592 buf().putLong(index, value);
593 return this;
594 }
595
596 @Override
597 public final LongBuffer asLongBuffer() {
598 return buf().asLongBuffer();
599 }
600
601 @Override
602 public final float getFloat() {
603 return buf().getFloat();
604 }
605
606 @Override
607 public final IoBuffer putFloat(float value) {
608 autoExpand(4);
609 buf().putFloat(value);
610 return this;
611 }
612
613 @Override
614 public final float getFloat(int index) {
615 return buf().getFloat(index);
616 }
617
618 @Override
619 public final IoBuffer putFloat(int index, float value) {
620 autoExpand(index, 4);
621 buf().putFloat(index, value);
622 return this;
623 }
624
625 @Override
626 public final FloatBuffer asFloatBuffer() {
627 return buf().asFloatBuffer();
628 }
629
630 @Override
631 public final double getDouble() {
632 return buf().getDouble();
633 }
634
635 @Override
636 public final IoBuffer putDouble(double value) {
637 autoExpand(8);
638 buf().putDouble(value);
639 return this;
640 }
641
642 @Override
643 public final double getDouble(int index) {
644 return buf().getDouble(index);
645 }
646
647 @Override
648 public final IoBuffer putDouble(int index, double value) {
649 autoExpand(index, 8);
650 buf().putDouble(index, value);
651 return this;
652 }
653
654 @Override
655 public final DoubleBuffer asDoubleBuffer() {
656 return buf().asDoubleBuffer();
657 }
658
659 @Override
660 public final IoBuffer asReadOnlyBuffer() {
661 recapacityAllowed = false;
662 return asReadOnlyBuffer0();
663 }
664
665
666
667
668
669 protected abstract IoBuffer asReadOnlyBuffer0();
670
671 @Override
672 public final IoBuffer duplicate() {
673 recapacityAllowed = false;
674 return duplicate0();
675 }
676
677
678
679
680
681 protected abstract IoBuffer duplicate0();
682
683 @Override
684 public final IoBuffer slice() {
685 recapacityAllowed = false;
686 return slice0();
687 }
688
689 @Override
690 public final IoBuffer getSlice(int index, int length) {
691 if (length < 0) {
692 throw new IllegalArgumentException("length: " + length);
693 }
694 int pos = position();
695 int limit = limit();
696 int endIndex = pos + length;
697
698 if (capacity() < endIndex) {
699 throw new IndexOutOfBoundsException(
700 "index + length (" + endIndex + ") is greater " +
701 "than capacity (" + capacity() + ").");
702 }
703
704 clear();
705 position(index);
706 limit(endIndex);
707
708 IoBuffer slice = slice();
709 position(pos);
710 limit(limit);
711 return slice;
712 }
713
714 @Override
715 public final IoBuffer getSlice(int length) {
716 if (length < 0) {
717 throw new IllegalArgumentException("length: " + length);
718 }
719 int pos = position();
720 int limit = limit();
721 int nextPos = pos + length;
722 if (limit < nextPos) {
723 throw new IndexOutOfBoundsException(
724 "position + length (" + nextPos + ") is greater " +
725 "than limit (" + limit + ").");
726 }
727
728 limit(pos + length);
729 IoBuffer slice = slice();
730 position(nextPos);
731 limit(limit);
732 return slice;
733 }
734
735
736
737
738
739 protected abstract IoBuffer slice0();
740
741 @Override
742 public int hashCode() {
743 int h = 1;
744 int p = position();
745 for (int i = limit() - 1; i >= p; i--) {
746 h = 31 * h + get(i);
747 }
748 return h;
749 }
750
751 @Override
752 public boolean equals(Object o) {
753 if (!(o instanceof IoBuffer)) {
754 return false;
755 }
756
757 IoBuffer that = (IoBuffer) o;
758 if (this.remaining() != that.remaining()) {
759 return false;
760 }
761
762 int p = this.position();
763 for (int i = this.limit() - 1, j = that.limit() - 1; i >= p; i--, j--) {
764 byte v1 = this.get(i);
765 byte v2 = that.get(j);
766 if (v1 != v2) {
767 return false;
768 }
769 }
770 return true;
771 }
772
773 public int compareTo(IoBuffer that) {
774 int n = this.position() + Math.min(this.remaining(), that.remaining());
775 for (int i = this.position(), j = that.position(); i < n; i++, j++) {
776 byte v1 = this.get(i);
777 byte v2 = that.get(j);
778 if (v1 == v2) {
779 continue;
780 }
781 if (v1 < v2) {
782 return -1;
783 }
784
785 return +1;
786 }
787 return this.remaining() - that.remaining();
788 }
789
790 @Override
791 public String toString() {
792 StringBuffer buf = new StringBuffer();
793 if (isDirect()) {
794 buf.append("DirectBuffer");
795 } else {
796 buf.append("HeapBuffer");
797 }
798 buf.append("[pos=");
799 buf.append(position());
800 buf.append(" lim=");
801 buf.append(limit());
802 buf.append(" cap=");
803 buf.append(capacity());
804 buf.append(": ");
805 buf.append(getHexDump(16));
806 buf.append(']');
807 return buf.toString();
808 }
809
810 @Override
811 public IoBuffer get(byte[] dst) {
812 return get(dst, 0, dst.length);
813 }
814
815 @Override
816 public IoBuffer put(IoBuffer src) {
817 return put(src.buf());
818 }
819
820 @Override
821 public IoBuffer put(byte[] src) {
822 return put(src, 0, src.length);
823 }
824
825 @Override
826 public int getUnsignedShort() {
827 return getShort() & 0xffff;
828 }
829
830 @Override
831 public int getUnsignedShort(int index) {
832 return getShort(index) & 0xffff;
833 }
834
835 @Override
836 public long getUnsignedInt() {
837 return getInt() & 0xffffffffL;
838 }
839
840 @Override
841 public int getMediumInt() {
842 byte b1 = get();
843 byte b2 = get();
844 byte b3 = get();
845 if (ByteOrder.BIG_ENDIAN.equals(order())) {
846 return getMediumInt(b1, b2, b3);
847 } else {
848 return getMediumInt(b3, b2, b1);
849 }
850 }
851
852 @Override
853 public int getUnsignedMediumInt() {
854 int b1 = getUnsigned();
855 int b2 = getUnsigned();
856 int b3 = getUnsigned();
857 if (ByteOrder.BIG_ENDIAN.equals(order())) {
858 return b1 << 16 | b2 << 8 | b3;
859 } else {
860 return b3 << 16 | b2 << 8 | b1;
861 }
862 }
863
864 @Override
865 public int getMediumInt(int index) {
866 byte b1 = get(index);
867 byte b2 = get(index + 1);
868 byte b3 = get(index + 2);
869 if (ByteOrder.BIG_ENDIAN.equals(order())) {
870 return getMediumInt(b1, b2, b3);
871 } else {
872 return getMediumInt(b3, b2, b1);
873 }
874 }
875
876 @Override
877 public int getUnsignedMediumInt(int index) {
878 int b1 = getUnsigned(index);
879 int b2 = getUnsigned(index + 1);
880 int b3 = getUnsigned(index + 2);
881 if (ByteOrder.BIG_ENDIAN.equals(order())) {
882 return b1 << 16 | b2 << 8 | b3;
883 } else {
884 return b3 << 16 | b2 << 8 | b1;
885 }
886 }
887
888 private int getMediumInt(byte b1, byte b2, byte b3) {
889 int ret = b1 << 16 & 0xff0000 | b2 << 8 & 0xff00 | b3 & 0xff;
890
891 if ((b1 & 0x80) == 0x80) {
892
893 ret |= 0xff000000;
894 }
895 return ret;
896 }
897
898 @Override
899 public IoBuffer putMediumInt(int value) {
900 byte b1 = (byte) (value >> 16);
901 byte b2 = (byte) (value >> 8);
902 byte b3 = (byte) value;
903
904 if (ByteOrder.BIG_ENDIAN.equals(order())) {
905 put(b1).put(b2).put(b3);
906 } else {
907 put(b3).put(b2).put(b1);
908 }
909
910 return this;
911 }
912
913 @Override
914 public IoBuffer putMediumInt(int index, int value) {
915 byte b1 = (byte) (value >> 16);
916 byte b2 = (byte) (value >> 8);
917 byte b3 = (byte) value;
918
919 if (ByteOrder.BIG_ENDIAN.equals(order())) {
920 put(index, b1).put(index + 1, b2).put(index + 2, b3);
921 } else {
922 put(index, b3).put(index + 1, b2).put(index + 2, b1);
923 }
924
925 return this;
926 }
927
928 @Override
929 public long getUnsignedInt(int index) {
930 return getInt(index) & 0xffffffffL;
931 }
932
933 @Override
934 public InputStream asInputStream() {
935 return new InputStream() {
936 @Override
937 public int available() {
938 return AbstractIoBuffer.this.remaining();
939 }
940
941 @Override
942 public synchronized void mark(int readlimit) {
943 AbstractIoBuffer.this.mark();
944 }
945
946 @Override
947 public boolean markSupported() {
948 return true;
949 }
950
951 @Override
952 public int read() {
953 if (AbstractIoBuffer.this.hasRemaining()) {
954 return AbstractIoBuffer.this.get() & 0xff;
955 } else {
956 return -1;
957 }
958 }
959
960 @Override
961 public int read(byte[] b, int off, int len) {
962 int remaining = AbstractIoBuffer.this.remaining();
963 if (remaining > 0) {
964 int readBytes = Math.min(remaining, len);
965 AbstractIoBuffer.this.get(b, off, readBytes);
966 return readBytes;
967 } else {
968 return -1;
969 }
970 }
971
972 @Override
973 public synchronized void reset() {
974 AbstractIoBuffer.this.reset();
975 }
976
977 @Override
978 public long skip(long n) {
979 int bytes;
980 if (n > Integer.MAX_VALUE) {
981 bytes = AbstractIoBuffer.this.remaining();
982 } else {
983 bytes = Math.min(AbstractIoBuffer.this.remaining(), (int) n);
984 }
985 AbstractIoBuffer.this.skip(bytes);
986 return bytes;
987 }
988 };
989 }
990
991 @Override
992 public OutputStream asOutputStream() {
993 return new OutputStream() {
994 @Override
995 public void write(byte[] b, int off, int len) {
996 AbstractIoBuffer.this.put(b, off, len);
997 }
998
999 @Override
1000 public void write(int b) {
1001 AbstractIoBuffer.this.put((byte) b);
1002 }
1003 };
1004 }
1005
1006 @Override
1007 public String getHexDump() {
1008 return this.getHexDump(Integer.MAX_VALUE);
1009 }
1010
1011 @Override
1012 public String getHexDump(int lengthLimit) {
1013 return IoBufferHexDumper.getHexdump(this, lengthLimit);
1014 }
1015
1016 @Override
1017 public String getString(CharsetDecoder decoder) throws CharacterCodingException {
1018 if (!hasRemaining()) {
1019 return "";
1020 }
1021
1022 boolean utf16 = decoder.charset().name().startsWith("UTF-16");
1023
1024 int oldPos = position();
1025 int oldLimit = limit();
1026 int end = -1;
1027 int newPos;
1028
1029 if (!utf16) {
1030 end = indexOf((byte) 0x00);
1031 if (end < 0) {
1032 newPos = end = oldLimit;
1033 } else {
1034 newPos = end + 1;
1035 }
1036 } else {
1037 int i = oldPos;
1038 for (;;) {
1039 boolean wasZero = get(i) == 0;
1040 i++;
1041
1042 if (i >= oldLimit) {
1043 break;
1044 }
1045
1046 if (get(i) != 0) {
1047 i++;
1048 if (i >= oldLimit) {
1049 break;
1050 } else {
1051 continue;
1052 }
1053 }
1054
1055 if (wasZero) {
1056 end = i - 1;
1057 break;
1058 }
1059 }
1060
1061 if (end < 0) {
1062 newPos = end = oldPos + (oldLimit - oldPos & 0xFFFFFFFE);
1063 } else {
1064 if (end + 2 <= oldLimit) {
1065 newPos = end + 2;
1066 } else {
1067 newPos = end;
1068 }
1069 }
1070 }
1071
1072 if (oldPos == end) {
1073 position(newPos);
1074 return "";
1075 }
1076
1077 limit(end);
1078 decoder.reset();
1079
1080 int expectedLength = (int) (remaining() * decoder.averageCharsPerByte()) + 1;
1081 CharBuffer out = CharBuffer.allocate(expectedLength);
1082 for (;;) {
1083 CoderResult cr;
1084 if (hasRemaining()) {
1085 cr = decoder.decode(buf(), out, true);
1086 } else {
1087 cr = decoder.flush(out);
1088 }
1089
1090 if (cr.isUnderflow()) {
1091 break;
1092 }
1093
1094 if (cr.isOverflow()) {
1095 CharBuffer o = CharBuffer.allocate(out.capacity()
1096 + expectedLength);
1097 out.flip();
1098 o.put(out);
1099 out = o;
1100 continue;
1101 }
1102
1103 if (cr.isError()) {
1104
1105 limit(oldLimit);
1106 position(oldPos);
1107 cr.throwException();
1108 }
1109 }
1110
1111 limit(oldLimit);
1112 position(newPos);
1113 return out.flip().toString();
1114 }
1115
1116 @Override
1117 public String getString(int fieldSize, CharsetDecoder decoder)
1118 throws CharacterCodingException {
1119 checkFieldSize(fieldSize);
1120
1121 if (fieldSize == 0) {
1122 return "";
1123 }
1124
1125 if (!hasRemaining()) {
1126 return "";
1127 }
1128
1129 boolean utf16 = decoder.charset().name().startsWith("UTF-16");
1130
1131 if (utf16 && (fieldSize & 1) != 0) {
1132 throw new IllegalArgumentException("fieldSize is not even.");
1133 }
1134
1135 int oldPos = position();
1136 int oldLimit = limit();
1137 int end = oldPos + fieldSize;
1138
1139 if (oldLimit < end) {
1140 throw new BufferUnderflowException();
1141 }
1142
1143 int i;
1144
1145 if (!utf16) {
1146 for (i = oldPos; i < end; i++) {
1147 if (get(i) == 0) {
1148 break;
1149 }
1150 }
1151
1152 if (i == end) {
1153 limit(end);
1154 } else {
1155 limit(i);
1156 }
1157 } else {
1158 for (i = oldPos; i < end; i += 2) {
1159 if (get(i) == 0 && get(i + 1) == 0) {
1160 break;
1161 }
1162 }
1163
1164 if (i == end) {
1165 limit(end);
1166 } else {
1167 limit(i);
1168 }
1169 }
1170
1171 if (!hasRemaining()) {
1172 limit(oldLimit);
1173 position(end);
1174 return "";
1175 }
1176 decoder.reset();
1177
1178 int expectedLength = (int) (remaining() * decoder.averageCharsPerByte()) + 1;
1179 CharBuffer out = CharBuffer.allocate(expectedLength);
1180 for (;;) {
1181 CoderResult cr;
1182 if (hasRemaining()) {
1183 cr = decoder.decode(buf(), out, true);
1184 } else {
1185 cr = decoder.flush(out);
1186 }
1187
1188 if (cr.isUnderflow()) {
1189 break;
1190 }
1191
1192 if (cr.isOverflow()) {
1193 CharBuffer o = CharBuffer.allocate(out.capacity()
1194 + expectedLength);
1195 out.flip();
1196 o.put(out);
1197 out = o;
1198 continue;
1199 }
1200
1201 if (cr.isError()) {
1202
1203 limit(oldLimit);
1204 position(oldPos);
1205 cr.throwException();
1206 }
1207 }
1208
1209 limit(oldLimit);
1210 position(end);
1211 return out.flip().toString();
1212 }
1213
1214 @Override
1215 public IoBuffer putString(CharSequence val, CharsetEncoder encoder)
1216 throws CharacterCodingException {
1217 if (val.length() == 0) {
1218 return this;
1219 }
1220
1221 CharBuffer in = CharBuffer.wrap(val);
1222 encoder.reset();
1223
1224 int expandedState = 0;
1225
1226 for (;;) {
1227 CoderResult cr;
1228 if (in.hasRemaining()) {
1229 cr = encoder.encode(in, buf(), true);
1230 } else {
1231 cr = encoder.flush(buf());
1232 }
1233
1234 if (cr.isUnderflow()) {
1235 break;
1236 }
1237 if (cr.isOverflow()) {
1238 if (isAutoExpand()) {
1239 switch (expandedState) {
1240 case 0:
1241 autoExpand((int) Math.ceil(in.remaining()
1242 * encoder.averageBytesPerChar()));
1243 expandedState++;
1244 break;
1245 case 1:
1246 autoExpand((int) Math.ceil(in.remaining()
1247 * encoder.maxBytesPerChar()));
1248 expandedState++;
1249 break;
1250 default:
1251 throw new RuntimeException("Expanded by "
1252 + (int) Math.ceil(in.remaining()
1253 * encoder.maxBytesPerChar())
1254 + " but that wasn't enough for '" + val + "'");
1255 }
1256 continue;
1257 }
1258 } else {
1259 expandedState = 0;
1260 }
1261 cr.throwException();
1262 }
1263 return this;
1264 }
1265
1266 @Override
1267 public IoBuffer putString(CharSequence val, int fieldSize, CharsetEncoder encoder)
1268 throws CharacterCodingException {
1269 checkFieldSize(fieldSize);
1270
1271 if (fieldSize == 0) {
1272 return this;
1273 }
1274
1275 autoExpand(fieldSize);
1276
1277 boolean utf16 = encoder.charset().name().startsWith("UTF-16");
1278
1279 if (utf16 && (fieldSize & 1) != 0) {
1280 throw new IllegalArgumentException("fieldSize is not even.");
1281 }
1282
1283 int oldLimit = limit();
1284 int end = position() + fieldSize;
1285
1286 if (oldLimit < end) {
1287 throw new BufferOverflowException();
1288 }
1289
1290 if (val.length() == 0) {
1291 if (!utf16) {
1292 put((byte) 0x00);
1293 } else {
1294 put((byte) 0x00);
1295 put((byte) 0x00);
1296 }
1297 position(end);
1298 return this;
1299 }
1300
1301 CharBuffer in = CharBuffer.wrap(val);
1302 limit(end);
1303 encoder.reset();
1304
1305 for (;;) {
1306 CoderResult cr;
1307 if (in.hasRemaining()) {
1308 cr = encoder.encode(in, buf(), true);
1309 } else {
1310 cr = encoder.flush(buf());
1311 }
1312
1313 if (cr.isUnderflow() || cr.isOverflow()) {
1314 break;
1315 }
1316 cr.throwException();
1317 }
1318
1319 limit(oldLimit);
1320
1321 if (position() < end) {
1322 if (!utf16) {
1323 put((byte) 0x00);
1324 } else {
1325 put((byte) 0x00);
1326 put((byte) 0x00);
1327 }
1328 }
1329
1330 position(end);
1331 return this;
1332 }
1333
1334 @Override
1335 public String getPrefixedString(CharsetDecoder decoder)
1336 throws CharacterCodingException {
1337 return getPrefixedString(2, decoder);
1338 }
1339
1340
1341
1342
1343
1344
1345
1346
1347
1348
1349
1350 @Override
1351 public String getPrefixedString(int prefixLength, CharsetDecoder decoder)
1352 throws CharacterCodingException {
1353 if (!prefixedDataAvailable(prefixLength)) {
1354 throw new BufferUnderflowException();
1355 }
1356
1357 int fieldSize = 0;
1358
1359 switch (prefixLength) {
1360 case 1:
1361 fieldSize = getUnsigned();
1362 break;
1363 case 2:
1364 fieldSize = getUnsignedShort();
1365 break;
1366 case 4:
1367 fieldSize = getInt();
1368 break;
1369 }
1370
1371 if (fieldSize == 0) {
1372 return "";
1373 }
1374
1375 boolean utf16 = decoder.charset().name().startsWith("UTF-16");
1376
1377 if (utf16 && (fieldSize & 1) != 0) {
1378 throw new BufferDataException(
1379 "fieldSize is not even for a UTF-16 string.");
1380 }
1381
1382 int oldLimit = limit();
1383 int end = position() + fieldSize;
1384
1385 if (oldLimit < end) {
1386 throw new BufferUnderflowException();
1387 }
1388
1389 limit(end);
1390 decoder.reset();
1391
1392 int expectedLength = (int) (remaining() * decoder.averageCharsPerByte()) + 1;
1393 CharBuffer out = CharBuffer.allocate(expectedLength);
1394 for (;;) {
1395 CoderResult cr;
1396 if (hasRemaining()) {
1397 cr = decoder.decode(buf(), out, true);
1398 } else {
1399 cr = decoder.flush(out);
1400 }
1401
1402 if (cr.isUnderflow()) {
1403 break;
1404 }
1405
1406 if (cr.isOverflow()) {
1407 CharBuffer o = CharBuffer.allocate(out.capacity()
1408 + expectedLength);
1409 out.flip();
1410 o.put(out);
1411 out = o;
1412 continue;
1413 }
1414
1415 cr.throwException();
1416 }
1417
1418 limit(oldLimit);
1419 position(end);
1420 return out.flip().toString();
1421 }
1422
1423 @Override
1424 public IoBuffer putPrefixedString(CharSequence in, CharsetEncoder encoder)
1425 throws CharacterCodingException {
1426 return putPrefixedString(in, 2, 0, encoder);
1427 }
1428
1429 @Override
1430 public IoBuffer putPrefixedString(CharSequence in, int prefixLength, CharsetEncoder encoder)
1431 throws CharacterCodingException {
1432 return putPrefixedString(in, prefixLength, 0, encoder);
1433 }
1434
1435 @Override
1436 public IoBuffer putPrefixedString(CharSequence in, int prefixLength, int padding,
1437 CharsetEncoder encoder) throws CharacterCodingException {
1438 return putPrefixedString(in, prefixLength, padding, (byte) 0, encoder);
1439 }
1440
1441 @Override
1442 public IoBuffer putPrefixedString(CharSequence val, int prefixLength, int padding,
1443 byte padValue, CharsetEncoder encoder) throws CharacterCodingException {
1444 int maxLength;
1445 switch (prefixLength) {
1446 case 1:
1447 maxLength = 255;
1448 break;
1449 case 2:
1450 maxLength = 65535;
1451 break;
1452 case 4:
1453 maxLength = Integer.MAX_VALUE;
1454 break;
1455 default:
1456 throw new IllegalArgumentException("prefixLength: " + prefixLength);
1457 }
1458
1459 if (val.length() > maxLength) {
1460 throw new IllegalArgumentException(
1461 "The specified string is too long.");
1462 }
1463 if (val.length() == 0) {
1464 switch (prefixLength) {
1465 case 1:
1466 put((byte) 0);
1467 break;
1468 case 2:
1469 putShort((short) 0);
1470 break;
1471 case 4:
1472 putInt(0);
1473 break;
1474 }
1475 return this;
1476 }
1477
1478 int padMask;
1479 switch (padding) {
1480 case 0:
1481 case 1:
1482 padMask = 0;
1483 break;
1484 case 2:
1485 padMask = 1;
1486 break;
1487 case 4:
1488 padMask = 3;
1489 break;
1490 default:
1491 throw new IllegalArgumentException("padding: " + padding);
1492 }
1493
1494 CharBuffer in = CharBuffer.wrap(val);
1495 int expectedLength = (int) (in.remaining() * encoder
1496 .averageBytesPerChar()) + 1;
1497
1498 skip(prefixLength);
1499 int oldPos = position();
1500 encoder.reset();
1501
1502 for (;;) {
1503 CoderResult cr;
1504 if (in.hasRemaining()) {
1505 cr = encoder.encode(in, buf(), true);
1506 } else {
1507 cr = encoder.flush(buf());
1508 }
1509
1510 if (position() - oldPos > maxLength) {
1511 throw new IllegalArgumentException(
1512 "The specified string is too long.");
1513 }
1514
1515 if (cr.isUnderflow()) {
1516 break;
1517 }
1518 if (cr.isOverflow() && isAutoExpand()) {
1519 autoExpand(expectedLength);
1520 continue;
1521 }
1522 cr.throwException();
1523 }
1524
1525
1526 fill(padValue, padding - (position() - oldPos & padMask));
1527 int length = position() - oldPos;
1528 switch (prefixLength) {
1529 case 1:
1530 put(oldPos - 1, (byte) length);
1531 break;
1532 case 2:
1533 putShort(oldPos - 2, (short) length);
1534 break;
1535 case 4:
1536 putInt(oldPos - 4, length);
1537 break;
1538 }
1539 return this;
1540 }
1541
1542 @Override
1543 public Object getObject() throws ClassNotFoundException {
1544 return getObject(Thread.currentThread().getContextClassLoader());
1545 }
1546
1547 @Override
1548 public Object getObject(final ClassLoader classLoader) throws ClassNotFoundException {
1549 if (!prefixedDataAvailable(4)) {
1550 throw new BufferUnderflowException();
1551 }
1552
1553 int length = getInt();
1554 if (length <= 4) {
1555 throw new BufferDataException(
1556 "Object length should be greater than 4: " + length);
1557 }
1558
1559 int oldLimit = limit();
1560 limit(position() + length);
1561 try {
1562 ObjectInputStream in = new ObjectInputStream(asInputStream()) {
1563 @Override
1564 protected ObjectStreamClass readClassDescriptor()
1565 throws IOException, ClassNotFoundException {
1566 int type = read();
1567 if (type < 0) {
1568 throw new EOFException();
1569 }
1570 switch (type) {
1571 case 0:
1572 return super.readClassDescriptor();
1573 case 1:
1574 String className = readUTF();
1575 Class<?> clazz =
1576 Class.forName(className, true, classLoader);
1577 return ObjectStreamClass.lookup(clazz);
1578 default:
1579 throw new StreamCorruptedException(
1580 "Unexpected class descriptor type: " + type);
1581 }
1582 }
1583
1584 @Override
1585 protected Class<?> resolveClass(ObjectStreamClass desc) throws IOException, ClassNotFoundException {
1586 String name = desc.getName();
1587 try {
1588 return Class.forName(name, false, classLoader);
1589 } catch (ClassNotFoundException ex) {
1590 return super.resolveClass(desc);
1591 }
1592 }
1593 };
1594 return in.readObject();
1595 } catch (IOException e) {
1596 throw new BufferDataException(e);
1597 } finally {
1598 limit(oldLimit);
1599 }
1600 }
1601
1602 @Override
1603 public IoBuffer putObject(Object o) {
1604 int oldPos = position();
1605 skip(4);
1606 try {
1607 ObjectOutputStream out = new ObjectOutputStream(asOutputStream()) {
1608 @Override
1609 protected void writeClassDescriptor(ObjectStreamClass desc)
1610 throws IOException {
1611 String className = desc.getName();
1612 if (primitiveTypeNames.contains(className)) {
1613 write(0);
1614 super.writeClassDescriptor(desc);
1615 } else {
1616 write(1);
1617 writeUTF(desc.getName());
1618 }
1619 }
1620 };
1621 out.writeObject(o);
1622 out.flush();
1623 } catch (IOException e) {
1624 throw new BufferDataException(e);
1625 }
1626
1627
1628 int newPos = position();
1629 position(oldPos);
1630 putInt(newPos - oldPos - 4);
1631 position(newPos);
1632 return this;
1633 }
1634
1635 @Override
1636 public boolean prefixedDataAvailable(int prefixLength) {
1637 return prefixedDataAvailable(prefixLength, Integer.MAX_VALUE);
1638 }
1639
1640 @Override
1641 public boolean prefixedDataAvailable(int prefixLength, int maxDataLength) {
1642 if (remaining() < prefixLength) {
1643 return false;
1644 }
1645
1646 int dataLength;
1647 switch (prefixLength) {
1648 case 1:
1649 dataLength = getUnsigned(position());
1650 break;
1651 case 2:
1652 dataLength = getUnsignedShort(position());
1653 break;
1654 case 4:
1655 dataLength = getInt(position());
1656 break;
1657 default:
1658 throw new IllegalArgumentException("prefixLength: " + prefixLength);
1659 }
1660
1661 if (dataLength < 0 || dataLength > maxDataLength) {
1662 throw new BufferDataException("dataLength: " + dataLength);
1663 }
1664
1665 return remaining() - prefixLength >= dataLength;
1666 }
1667
1668 @Override
1669 public int indexOf(byte b) {
1670 if (hasArray()) {
1671 int arrayOffset = arrayOffset();
1672 int beginPos = arrayOffset + position();
1673 int limit = arrayOffset + limit();
1674 byte[] array = array();
1675
1676 for (int i = beginPos; i < limit; i++) {
1677 if (array[i] == b) {
1678 return i - arrayOffset;
1679 }
1680 }
1681 } else {
1682 int beginPos = position();
1683 int limit = limit();
1684
1685 for (int i = beginPos; i < limit; i++) {
1686 if (get(i) == b) {
1687 return i;
1688 }
1689 }
1690 }
1691
1692 return -1;
1693 }
1694
1695 @Override
1696 public IoBuffer skip(int size) {
1697 autoExpand(size);
1698 return position(position() + size);
1699 }
1700
1701 @Override
1702 public IoBuffer fill(byte value, int size) {
1703 autoExpand(size);
1704 int q = size >>> 3;
1705 int r = size & 7;
1706
1707 if (q > 0) {
1708 int intValue = value | value << 8 | value << 16 | value << 24;
1709 long longValue = intValue;
1710 longValue <<= 32;
1711 longValue |= intValue;
1712
1713 for (int i = q; i > 0; i--) {
1714 putLong(longValue);
1715 }
1716 }
1717
1718 q = r >>> 2;
1719 r = r & 3;
1720
1721 if (q > 0) {
1722 int intValue = value | value << 8 | value << 16 | value << 24;
1723 putInt(intValue);
1724 }
1725
1726 q = r >> 1;
1727 r = r & 1;
1728
1729 if (q > 0) {
1730 short shortValue = (short) (value | value << 8);
1731 putShort(shortValue);
1732 }
1733
1734 if (r > 0) {
1735 put(value);
1736 }
1737
1738 return this;
1739 }
1740
1741 @Override
1742 public IoBuffer fillAndReset(byte value, int size) {
1743 autoExpand(size);
1744 int pos = position();
1745 try {
1746 fill(value, size);
1747 } finally {
1748 position(pos);
1749 }
1750 return this;
1751 }
1752
1753 @Override
1754 public IoBuffer fill(int size) {
1755 autoExpand(size);
1756 int q = size >>> 3;
1757 int r = size & 7;
1758
1759 for (int i = q; i > 0; i--) {
1760 putLong(0L);
1761 }
1762
1763 q = r >>> 2;
1764 r = r & 3;
1765
1766 if (q > 0) {
1767 putInt(0);
1768 }
1769
1770 q = r >> 1;
1771 r = r & 1;
1772
1773 if (q > 0) {
1774 putShort((short) 0);
1775 }
1776
1777 if (r > 0) {
1778 put((byte) 0);
1779 }
1780
1781 return this;
1782 }
1783
1784 @Override
1785 public IoBuffer fillAndReset(int size) {
1786 autoExpand(size);
1787 int pos = position();
1788 try {
1789 fill(size);
1790 } finally {
1791 position(pos);
1792 }
1793
1794 return this;
1795 }
1796
1797 private static final long BYTE_MASK = 0xFFL;
1798 private static final long SHORT_MASK = 0xFFFFL;
1799 private static final long INT_MASK = 0xFFFFFFFFL;
1800
1801 @Override
1802 public <E extends Enum<E>> E getEnum(Class<E> enumClass) {
1803 return toEnum(enumClass, get());
1804 }
1805
1806 @Override
1807 public <E extends Enum<E>> E getEnum(int index, Class<E> enumClass) {
1808 return toEnum(enumClass, get(index));
1809 }
1810
1811 @Override
1812 public <E extends Enum<E>> E getEnumShort(Class<E> enumClass) {
1813 return toEnum(enumClass, getShort());
1814 }
1815
1816 @Override
1817 public <E extends Enum<E>> E getEnumShort(int index, Class<E> enumClass) {
1818 return toEnum(enumClass, getShort(index));
1819 }
1820
1821 @Override
1822 public <E extends Enum<E>> E getEnumInt(Class<E> enumClass) {
1823 return toEnum(enumClass, getInt());
1824 }
1825
1826 @Override
1827 public <E extends Enum<E>> E getEnumInt(int index, Class<E> enumClass) {
1828 return toEnum(enumClass, getInt(index));
1829 }
1830
1831 @Override
1832 public IoBuffer putEnum(Enum<?> e) {
1833 if (e.ordinal() > Byte.MAX_VALUE) {
1834 throw new IllegalArgumentException(enumConversionErrorMessage(e,
1835 "byte"));
1836 }
1837 return put((byte) e.ordinal());
1838 }
1839
1840 @Override
1841 public IoBuffer putEnum(int index, Enum<?> e) {
1842 if (e.ordinal() > Byte.MAX_VALUE) {
1843 throw new IllegalArgumentException(enumConversionErrorMessage(e,
1844 "byte"));
1845 }
1846 return put(index, (byte) e.ordinal());
1847 }
1848
1849 @Override
1850 public IoBuffer putEnumShort(Enum<?> e) {
1851 if (e.ordinal() > Short.MAX_VALUE) {
1852 throw new IllegalArgumentException(enumConversionErrorMessage(e,
1853 "short"));
1854 }
1855 return putShort((short) e.ordinal());
1856 }
1857
1858 @Override
1859 public IoBuffer putEnumShort(int index, Enum<?> e) {
1860 if (e.ordinal() > Short.MAX_VALUE) {
1861 throw new IllegalArgumentException(enumConversionErrorMessage(e,
1862 "short"));
1863 }
1864 return putShort(index, (short) e.ordinal());
1865 }
1866
1867 @Override
1868 public IoBuffer putEnumInt(Enum<?> e) {
1869 return putInt(e.ordinal());
1870 }
1871
1872 @Override
1873 public IoBuffer putEnumInt(int index, Enum<?> e) {
1874 return putInt(index, e.ordinal());
1875 }
1876
1877 private <E> E toEnum(Class<E> enumClass, int i) {
1878 E[] enumConstants = enumClass.getEnumConstants();
1879 if (i > enumConstants.length) {
1880 throw new IndexOutOfBoundsException(String.format(
1881 "%d is too large of an ordinal to convert to the enum %s",
1882 i, enumClass.getName()));
1883 }
1884 return enumConstants[i];
1885 }
1886
1887 private String enumConversionErrorMessage(Enum<?> e, String type) {
1888 return String.format("%s.%s has an ordinal value too large for a %s", e
1889 .getClass().getName(), e.name(), type);
1890 }
1891
1892 @Override
1893 public <E extends Enum<E>> EnumSet<E> getEnumSet(Class<E> enumClass) {
1894 return toEnumSet(enumClass, get() & BYTE_MASK);
1895 }
1896
1897 @Override
1898 public <E extends Enum<E>> EnumSet<E> getEnumSet(int index, Class<E> enumClass) {
1899 return toEnumSet(enumClass, get(index) & BYTE_MASK);
1900 }
1901
1902 @Override
1903 public <E extends Enum<E>> EnumSet<E> getEnumSetShort(Class<E> enumClass) {
1904 return toEnumSet(enumClass, getShort() & SHORT_MASK);
1905 }
1906
1907 @Override
1908 public <E extends Enum<E>> EnumSet<E> getEnumSetShort(int index, Class<E> enumClass) {
1909 return toEnumSet(enumClass, getShort(index) & SHORT_MASK);
1910 }
1911
1912 @Override
1913 public <E extends Enum<E>> EnumSet<E> getEnumSetInt(Class<E> enumClass) {
1914 return toEnumSet(enumClass, getInt() & INT_MASK);
1915 }
1916
1917 @Override
1918 public <E extends Enum<E>> EnumSet<E> getEnumSetInt(int index, Class<E> enumClass) {
1919 return toEnumSet(enumClass, getInt(index) & INT_MASK);
1920 }
1921
1922 @Override
1923 public <E extends Enum<E>> EnumSet<E> getEnumSetLong(Class<E> enumClass) {
1924 return toEnumSet(enumClass, getLong());
1925 }
1926
1927 @Override
1928 public <E extends Enum<E>> EnumSet<E> getEnumSetLong(int index, Class<E> enumClass) {
1929 return toEnumSet(enumClass, getLong(index));
1930 }
1931
1932 private <E extends Enum<E>> EnumSet<E> toEnumSet(Class<E> clazz, long vector) {
1933 EnumSet<E> set = EnumSet.noneOf(clazz);
1934 long mask = 1;
1935 for (E e : clazz.getEnumConstants()) {
1936 if ((mask & vector) == mask) {
1937 set.add(e);
1938 }
1939 mask <<= 1;
1940 }
1941 return set;
1942 }
1943
1944 @Override
1945 public <E extends Enum<E>> IoBuffer putEnumSet(Set<E> set) {
1946 long vector = toLong(set);
1947 if ((vector & ~BYTE_MASK) != 0) {
1948 throw new IllegalArgumentException(
1949 "The enum set is too large to fit in a byte: " + set);
1950 }
1951 return put((byte) vector);
1952 }
1953
1954 @Override
1955 public <E extends Enum<E>> IoBuffer putEnumSet(int index, Set<E> set) {
1956 long vector = toLong(set);
1957 if ((vector & ~BYTE_MASK) != 0) {
1958 throw new IllegalArgumentException(
1959 "The enum set is too large to fit in a byte: " + set);
1960 }
1961 return put(index, (byte) vector);
1962 }
1963
1964 @Override
1965 public <E extends Enum<E>> IoBuffer putEnumSetShort(Set<E> set) {
1966 long vector = toLong(set);
1967 if ((vector & ~SHORT_MASK) != 0) {
1968 throw new IllegalArgumentException(
1969 "The enum set is too large to fit in a short: " + set);
1970 }
1971 return putShort((short) vector);
1972 }
1973
1974 @Override
1975 public <E extends Enum<E>> IoBuffer putEnumSetShort(int index, Set<E> set) {
1976 long vector = toLong(set);
1977 if ((vector & ~SHORT_MASK) != 0) {
1978 throw new IllegalArgumentException(
1979 "The enum set is too large to fit in a short: " + set);
1980 }
1981 return putShort(index, (short) vector);
1982 }
1983
1984 @Override
1985 public <E extends Enum<E>> IoBuffer putEnumSetInt(Set<E> set) {
1986 long vector = toLong(set);
1987 if ((vector & ~INT_MASK) != 0) {
1988 throw new IllegalArgumentException(
1989 "The enum set is too large to fit in an int: " + set);
1990 }
1991 return putInt((int) vector);
1992 }
1993
1994 @Override
1995 public <E extends Enum<E>> IoBuffer putEnumSetInt(int index, Set<E> set) {
1996 long vector = toLong(set);
1997 if ((vector & ~INT_MASK) != 0) {
1998 throw new IllegalArgumentException(
1999 "The enum set is too large to fit in an int: " + set);
2000 }
2001 return putInt(index, (int) vector);
2002 }
2003
2004 @Override
2005 public <E extends Enum<E>> IoBuffer putEnumSetLong(Set<E> set) {
2006 return putLong(toLong(set));
2007 }
2008
2009 @Override
2010 public <E extends Enum<E>> IoBuffer putEnumSetLong(int index, Set<E> set) {
2011 return putLong(index, toLong(set));
2012 }
2013
2014 private <E extends Enum<E>> long toLong(Set<E> set) {
2015 long vector = 0;
2016 for (E e : set) {
2017 if (e.ordinal() >= Long.SIZE) {
2018 throw new IllegalArgumentException(
2019 "The enum set is too large to fit in a bit vector: "
2020 + set);
2021 }
2022 vector |= 1L << e.ordinal();
2023 }
2024 return vector;
2025 }
2026
2027
2028
2029
2030
2031 private IoBuffer autoExpand(int expectedRemaining) {
2032 if (isAutoExpand()) {
2033 expand(expectedRemaining);
2034 }
2035 return this;
2036 }
2037
2038
2039
2040
2041
2042 private IoBuffer autoExpand(int pos, int expectedRemaining) {
2043 if (isAutoExpand()) {
2044 expand(pos, expectedRemaining);
2045 }
2046 return this;
2047 }
2048
2049 private static void checkFieldSize(int fieldSize) {
2050 if (fieldSize < 0) {
2051 throw new IllegalArgumentException("fieldSize cannot be negative: "
2052 + fieldSize);
2053 }
2054 }
2055 }