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