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