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