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