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