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