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( (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( index, (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( (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( index, (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( index, 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( index, (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)(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( index, (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( index, 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( index, (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( index, (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 pos = position();
1187 int limit = limit();
1188
1189 if (index > limit) {
1190 throw new IllegalArgumentException("index: " + index);
1191 }
1192
1193 int endIndex = index + length;
1194
1195 if (endIndex > limit) {
1196 throw new IndexOutOfBoundsException("index + length (" + endIndex
1197 + ") is greater " + "than limit (" + limit + ").");
1198 }
1199
1200 clear();
1201 position(index);
1202 limit(endIndex);
1203
1204 IoBuffer slice = slice();
1205 position(pos);
1206 limit(limit);
1207
1208 return slice;
1209 }
1210
1211
1212
1213
1214 @Override
1215 public final IoBuffer getSlice(int length) {
1216 if (length < 0) {
1217 throw new IllegalArgumentException("length: " + length);
1218 }
1219 int pos = position();
1220 int limit = limit();
1221 int nextPos = pos + length;
1222 if (limit < nextPos) {
1223 throw new IndexOutOfBoundsException("position + length (" + nextPos
1224 + ") is greater " + "than limit (" + limit + ").");
1225 }
1226
1227 limit(pos + length);
1228 IoBuffer slice = slice();
1229 position(nextPos);
1230 limit(limit);
1231 return slice;
1232 }
1233
1234
1235
1236
1237
1238 protected abstract IoBuffer slice0();
1239
1240
1241
1242
1243 @Override
1244 public int hashCode() {
1245 int h = 1;
1246 int p = position();
1247 for (int i = limit() - 1; i >= p; i--) {
1248 h = 31 * h + get(i);
1249 }
1250 return h;
1251 }
1252
1253
1254
1255
1256 @Override
1257 public boolean equals(Object o) {
1258 if (!(o instanceof IoBuffer)) {
1259 return false;
1260 }
1261
1262 IoBuffer that = (IoBuffer) o;
1263 if (this.remaining() != that.remaining()) {
1264 return false;
1265 }
1266
1267 int p = this.position();
1268 for (int i = this.limit() - 1, j = that.limit() - 1; i >= p; i--, j--) {
1269 byte v1 = this.get(i);
1270 byte v2 = that.get(j);
1271 if (v1 != v2) {
1272 return false;
1273 }
1274 }
1275 return true;
1276 }
1277
1278
1279
1280
1281 public int compareTo(IoBuffer that) {
1282 int n = this.position() + Math.min(this.remaining(), that.remaining());
1283 for (int i = this.position(), j = that.position(); i < n; i++, j++) {
1284 byte v1 = this.get(i);
1285 byte v2 = that.get(j);
1286 if (v1 == v2) {
1287 continue;
1288 }
1289 if (v1 < v2) {
1290 return -1;
1291 }
1292
1293 return +1;
1294 }
1295 return this.remaining() - that.remaining();
1296 }
1297
1298
1299
1300
1301 @Override
1302 public String toString() {
1303 StringBuilder buf = new StringBuilder();
1304 if (isDirect()) {
1305 buf.append("DirectBuffer");
1306 } else {
1307 buf.append("HeapBuffer");
1308 }
1309 buf.append("[pos=");
1310 buf.append(position());
1311 buf.append(" lim=");
1312 buf.append(limit());
1313 buf.append(" cap=");
1314 buf.append(capacity());
1315 buf.append(": ");
1316 buf.append(getHexDump(16));
1317 buf.append(']');
1318 return buf.toString();
1319 }
1320
1321
1322
1323
1324 @Override
1325 public IoBuffer get(byte[] dst) {
1326 return get(dst, 0, dst.length);
1327 }
1328
1329
1330
1331
1332 @Override
1333 public IoBuffer put(IoBuffer src) {
1334 return put(src.buf());
1335 }
1336
1337
1338
1339
1340 @Override
1341 public IoBuffer put(byte[] src) {
1342 return put(src, 0, src.length);
1343 }
1344
1345
1346
1347
1348 @Override
1349 public int getUnsignedShort() {
1350 return getShort() & 0xffff;
1351 }
1352
1353
1354
1355
1356 @Override
1357 public int getUnsignedShort(int index) {
1358 return getShort(index) & 0xffff;
1359 }
1360
1361
1362
1363
1364 @Override
1365 public long getUnsignedInt() {
1366 return getInt() & 0xffffffffL;
1367 }
1368
1369
1370
1371
1372 @Override
1373 public int getMediumInt() {
1374 byte b1 = get();
1375 byte b2 = get();
1376 byte b3 = get();
1377 if (ByteOrder.BIG_ENDIAN.equals(order())) {
1378 return getMediumInt(b1, b2, b3);
1379 }
1380
1381 return getMediumInt(b3, b2, b1);
1382 }
1383
1384
1385
1386
1387 @Override
1388 public int getUnsignedMediumInt() {
1389 int b1 = getUnsigned();
1390 int b2 = getUnsigned();
1391 int b3 = getUnsigned();
1392 if (ByteOrder.BIG_ENDIAN.equals(order())) {
1393 return b1 << 16 | b2 << 8 | b3;
1394 }
1395
1396 return b3 << 16 | b2 << 8 | b1;
1397 }
1398
1399
1400
1401
1402 @Override
1403 public int getMediumInt(int index) {
1404 byte b1 = get(index);
1405 byte b2 = get(index + 1);
1406 byte b3 = get(index + 2);
1407 if (ByteOrder.BIG_ENDIAN.equals(order())) {
1408 return getMediumInt(b1, b2, b3);
1409 }
1410
1411 return getMediumInt(b3, b2, b1);
1412 }
1413
1414
1415
1416
1417 @Override
1418 public int getUnsignedMediumInt(int index) {
1419 int b1 = getUnsigned(index);
1420 int b2 = getUnsigned(index + 1);
1421 int b3 = getUnsigned(index + 2);
1422 if (ByteOrder.BIG_ENDIAN.equals(order())) {
1423 return b1 << 16 | b2 << 8 | b3;
1424 }
1425
1426 return b3 << 16 | b2 << 8 | b1;
1427 }
1428
1429
1430
1431
1432 private int getMediumInt(byte b1, byte b2, byte b3) {
1433 int ret = b1 << 16 & 0xff0000 | b2 << 8 & 0xff00 | b3 & 0xff;
1434
1435 if ((b1 & 0x80) == 0x80) {
1436
1437 ret |= 0xff000000;
1438 }
1439 return ret;
1440 }
1441
1442
1443
1444
1445 @Override
1446 public IoBuffer putMediumInt(int value) {
1447 byte b1 = (byte) (value >> 16);
1448 byte b2 = (byte) (value >> 8);
1449 byte b3 = (byte) value;
1450
1451 if (ByteOrder.BIG_ENDIAN.equals(order())) {
1452 put(b1).put(b2).put(b3);
1453 } else {
1454 put(b3).put(b2).put(b1);
1455 }
1456
1457 return this;
1458 }
1459
1460
1461
1462
1463 @Override
1464 public IoBuffer putMediumInt(int index, int value) {
1465 byte b1 = (byte) (value >> 16);
1466 byte b2 = (byte) (value >> 8);
1467 byte b3 = (byte) value;
1468
1469 if (ByteOrder.BIG_ENDIAN.equals(order())) {
1470 put(index, b1).put(index + 1, b2).put(index + 2, b3);
1471 } else {
1472 put(index, b3).put(index + 1, b2).put(index + 2, b1);
1473 }
1474
1475 return this;
1476 }
1477
1478
1479
1480
1481 @Override
1482 public long getUnsignedInt(int index) {
1483 return getInt(index) & 0xffffffffL;
1484 }
1485
1486
1487
1488
1489 @Override
1490 public InputStream asInputStream() {
1491 return new InputStream() {
1492 @Override
1493 public int available() {
1494 return AbstractIoBuffer.this.remaining();
1495 }
1496
1497 @Override
1498 public synchronized void mark(int readlimit) {
1499 AbstractIoBuffer.this.mark();
1500 }
1501
1502 @Override
1503 public boolean markSupported() {
1504 return true;
1505 }
1506
1507 @Override
1508 public int read() {
1509 if (AbstractIoBuffer.this.hasRemaining()) {
1510 return AbstractIoBuffer.this.get() & 0xff;
1511 }
1512
1513 return -1;
1514 }
1515
1516 @Override
1517 public int read(byte[] b, int off, int len) {
1518 int remaining = AbstractIoBuffer.this.remaining();
1519 if (remaining > 0) {
1520 int readBytes = Math.min(remaining, len);
1521 AbstractIoBuffer.this.get(b, off, readBytes);
1522 return readBytes;
1523 }
1524
1525 return -1;
1526 }
1527
1528 @Override
1529 public synchronized void reset() {
1530 AbstractIoBuffer.this.reset();
1531 }
1532
1533 @Override
1534 public long skip(long n) {
1535 int bytes;
1536 if (n > Integer.MAX_VALUE) {
1537 bytes = AbstractIoBuffer.this.remaining();
1538 } else {
1539 bytes = Math
1540 .min(AbstractIoBuffer.this.remaining(), (int) n);
1541 }
1542 AbstractIoBuffer.this.skip(bytes);
1543 return bytes;
1544 }
1545 };
1546 }
1547
1548
1549
1550
1551 @Override
1552 public OutputStream asOutputStream() {
1553 return new OutputStream() {
1554 @Override
1555 public void write(byte[] b, int off, int len) {
1556 AbstractIoBuffer.this.put(b, off, len);
1557 }
1558
1559 @Override
1560 public void write(int b) {
1561 AbstractIoBuffer.this.put((byte) b);
1562 }
1563 };
1564 }
1565
1566
1567
1568
1569 @Override
1570 public String getHexDump() {
1571 return this.getHexDump(Integer.MAX_VALUE);
1572 }
1573
1574
1575
1576
1577 @Override
1578 public String getHexDump(int lengthLimit) {
1579 return IoBufferHexDumper.getHexdump(this, lengthLimit);
1580 }
1581
1582
1583
1584
1585 @Override
1586 public String getString(CharsetDecoder decoder)
1587 throws CharacterCodingException {
1588 if (!hasRemaining()) {
1589 return "";
1590 }
1591
1592 boolean utf16 = decoder.charset().name().startsWith("UTF-16");
1593
1594 int oldPos = position();
1595 int oldLimit = limit();
1596 int end = -1;
1597 int newPos;
1598
1599 if (!utf16) {
1600 end = indexOf((byte) 0x00);
1601 if (end < 0) {
1602 newPos = end = oldLimit;
1603 } else {
1604 newPos = end + 1;
1605 }
1606 } else {
1607 int i = oldPos;
1608 for (;;) {
1609 boolean wasZero = get(i) == 0;
1610 i++;
1611
1612 if (i >= oldLimit) {
1613 break;
1614 }
1615
1616 if (get(i) != 0) {
1617 i++;
1618 if (i >= oldLimit) {
1619 break;
1620 }
1621
1622 continue;
1623 }
1624
1625 if (wasZero) {
1626 end = i - 1;
1627 break;
1628 }
1629 }
1630
1631 if (end < 0) {
1632 newPos = end = oldPos + (oldLimit - oldPos & 0xFFFFFFFE);
1633 } else {
1634 if (end + 2 <= oldLimit) {
1635 newPos = end + 2;
1636 } else {
1637 newPos = end;
1638 }
1639 }
1640 }
1641
1642 if (oldPos == end) {
1643 position(newPos);
1644 return "";
1645 }
1646
1647 limit(end);
1648 decoder.reset();
1649
1650 int expectedLength = (int) (remaining() * decoder.averageCharsPerByte()) + 1;
1651 CharBuffer out = CharBuffer.allocate(expectedLength);
1652 for (;;) {
1653 CoderResult cr;
1654 if (hasRemaining()) {
1655 cr = decoder.decode(buf(), out, true);
1656 } else {
1657 cr = decoder.flush(out);
1658 }
1659
1660 if (cr.isUnderflow()) {
1661 break;
1662 }
1663
1664 if (cr.isOverflow()) {
1665 CharBuffer o = CharBuffer.allocate(out.capacity()
1666 + expectedLength);
1667 out.flip();
1668 o.put(out);
1669 out = o;
1670 continue;
1671 }
1672
1673 if (cr.isError()) {
1674
1675 limit(oldLimit);
1676 position(oldPos);
1677 cr.throwException();
1678 }
1679 }
1680
1681 limit(oldLimit);
1682 position(newPos);
1683 return out.flip().toString();
1684 }
1685
1686
1687
1688
1689 @Override
1690 public String getString(int fieldSize, CharsetDecoder decoder)
1691 throws CharacterCodingException {
1692 checkFieldSize(fieldSize);
1693
1694 if (fieldSize == 0) {
1695 return "";
1696 }
1697
1698 if (!hasRemaining()) {
1699 return "";
1700 }
1701
1702 boolean utf16 = decoder.charset().name().startsWith("UTF-16");
1703
1704 if (utf16 && (fieldSize & 1) != 0) {
1705 throw new IllegalArgumentException("fieldSize is not even.");
1706 }
1707
1708 int oldPos = position();
1709 int oldLimit = limit();
1710 int end = oldPos + fieldSize;
1711
1712 if (oldLimit < end) {
1713 throw new BufferUnderflowException();
1714 }
1715
1716 int i;
1717
1718 if (!utf16) {
1719 for (i = oldPos; i < end; i++) {
1720 if (get(i) == 0) {
1721 break;
1722 }
1723 }
1724
1725 if (i == end) {
1726 limit(end);
1727 } else {
1728 limit(i);
1729 }
1730 } else {
1731 for (i = oldPos; i < end; i += 2) {
1732 if (get(i) == 0 && get(i + 1) == 0) {
1733 break;
1734 }
1735 }
1736
1737 if (i == end) {
1738 limit(end);
1739 } else {
1740 limit(i);
1741 }
1742 }
1743
1744 if (!hasRemaining()) {
1745 limit(oldLimit);
1746 position(end);
1747 return "";
1748 }
1749 decoder.reset();
1750
1751 int expectedLength = (int) (remaining() * decoder.averageCharsPerByte()) + 1;
1752 CharBuffer out = CharBuffer.allocate(expectedLength);
1753 for (;;) {
1754 CoderResult cr;
1755 if (hasRemaining()) {
1756 cr = decoder.decode(buf(), out, true);
1757 } else {
1758 cr = decoder.flush(out);
1759 }
1760
1761 if (cr.isUnderflow()) {
1762 break;
1763 }
1764
1765 if (cr.isOverflow()) {
1766 CharBuffer o = CharBuffer.allocate(out.capacity()
1767 + expectedLength);
1768 out.flip();
1769 o.put(out);
1770 out = o;
1771 continue;
1772 }
1773
1774 if (cr.isError()) {
1775
1776 limit(oldLimit);
1777 position(oldPos);
1778 cr.throwException();
1779 }
1780 }
1781
1782 limit(oldLimit);
1783 position(end);
1784 return out.flip().toString();
1785 }
1786
1787
1788
1789
1790 @Override
1791 public IoBuffer putString(CharSequence val, CharsetEncoder encoder)
1792 throws CharacterCodingException {
1793 if (val.length() == 0) {
1794 return this;
1795 }
1796
1797 CharBuffer in = CharBuffer.wrap(val);
1798 encoder.reset();
1799
1800 int expandedState = 0;
1801
1802 for (;;) {
1803 CoderResult cr;
1804 if (in.hasRemaining()) {
1805 cr = encoder.encode(in, buf(), true);
1806 } else {
1807 cr = encoder.flush(buf());
1808 }
1809
1810 if (cr.isUnderflow()) {
1811 break;
1812 }
1813 if (cr.isOverflow()) {
1814 if (isAutoExpand()) {
1815 switch (expandedState) {
1816 case 0:
1817 autoExpand((int) Math.ceil(in.remaining()
1818 * encoder.averageBytesPerChar()));
1819 expandedState++;
1820 break;
1821 case 1:
1822 autoExpand((int) Math.ceil(in.remaining()
1823 * encoder.maxBytesPerChar()));
1824 expandedState++;
1825 break;
1826 default:
1827 throw new RuntimeException("Expanded by "
1828 + (int) Math.ceil(in.remaining()
1829 * encoder.maxBytesPerChar())
1830 + " but that wasn't enough for '" + val + "'");
1831 }
1832 continue;
1833 }
1834 } else {
1835 expandedState = 0;
1836 }
1837 cr.throwException();
1838 }
1839 return this;
1840 }
1841
1842
1843
1844
1845 @Override
1846 public IoBuffer putString(CharSequence val, int fieldSize,
1847 CharsetEncoder encoder) throws CharacterCodingException {
1848 checkFieldSize(fieldSize);
1849
1850 if (fieldSize == 0) {
1851 return this;
1852 }
1853
1854 autoExpand(fieldSize);
1855
1856 boolean utf16 = encoder.charset().name().startsWith("UTF-16");
1857
1858 if (utf16 && (fieldSize & 1) != 0) {
1859 throw new IllegalArgumentException("fieldSize is not even.");
1860 }
1861
1862 int oldLimit = limit();
1863 int end = position() + fieldSize;
1864
1865 if (oldLimit < end) {
1866 throw new BufferOverflowException();
1867 }
1868
1869 if (val.length() == 0) {
1870 if (!utf16) {
1871 put((byte) 0x00);
1872 } else {
1873 put((byte) 0x00);
1874 put((byte) 0x00);
1875 }
1876 position(end);
1877 return this;
1878 }
1879
1880 CharBuffer in = CharBuffer.wrap(val);
1881 limit(end);
1882 encoder.reset();
1883
1884 for (;;) {
1885 CoderResult cr;
1886 if (in.hasRemaining()) {
1887 cr = encoder.encode(in, buf(), true);
1888 } else {
1889 cr = encoder.flush(buf());
1890 }
1891
1892 if (cr.isUnderflow() || cr.isOverflow()) {
1893 break;
1894 }
1895 cr.throwException();
1896 }
1897
1898 limit(oldLimit);
1899
1900 if (position() < end) {
1901 if (!utf16) {
1902 put((byte) 0x00);
1903 } else {
1904 put((byte) 0x00);
1905 put((byte) 0x00);
1906 }
1907 }
1908
1909 position(end);
1910 return this;
1911 }
1912
1913
1914
1915
1916 @Override
1917 public String getPrefixedString(CharsetDecoder decoder)
1918 throws CharacterCodingException {
1919 return getPrefixedString(2, decoder);
1920 }
1921
1922
1923
1924
1925
1926
1927
1928
1929
1930
1931
1932 @Override
1933 public String getPrefixedString(int prefixLength, CharsetDecoder decoder)
1934 throws CharacterCodingException {
1935 if (!prefixedDataAvailable(prefixLength)) {
1936 throw new BufferUnderflowException();
1937 }
1938
1939 int fieldSize = 0;
1940
1941 switch (prefixLength) {
1942 case 1:
1943 fieldSize = getUnsigned();
1944 break;
1945 case 2:
1946 fieldSize = getUnsignedShort();
1947 break;
1948 case 4:
1949 fieldSize = getInt();
1950 break;
1951 }
1952
1953 if (fieldSize == 0) {
1954 return "";
1955 }
1956
1957 boolean utf16 = decoder.charset().name().startsWith("UTF-16");
1958
1959 if (utf16 && (fieldSize & 1) != 0) {
1960 throw new BufferDataException(
1961 "fieldSize is not even for a UTF-16 string.");
1962 }
1963
1964 int oldLimit = limit();
1965 int end = position() + fieldSize;
1966
1967 if (oldLimit < end) {
1968 throw new BufferUnderflowException();
1969 }
1970
1971 limit(end);
1972 decoder.reset();
1973
1974 int expectedLength = (int) (remaining() * decoder.averageCharsPerByte()) + 1;
1975 CharBuffer out = CharBuffer.allocate(expectedLength);
1976 for (;;) {
1977 CoderResult cr;
1978 if (hasRemaining()) {
1979 cr = decoder.decode(buf(), out, true);
1980 } else {
1981 cr = decoder.flush(out);
1982 }
1983
1984 if (cr.isUnderflow()) {
1985 break;
1986 }
1987
1988 if (cr.isOverflow()) {
1989 CharBuffer o = CharBuffer.allocate(out.capacity()
1990 + expectedLength);
1991 out.flip();
1992 o.put(out);
1993 out = o;
1994 continue;
1995 }
1996
1997 cr.throwException();
1998 }
1999
2000 limit(oldLimit);
2001 position(end);
2002 return out.flip().toString();
2003 }
2004
2005
2006
2007
2008 @Override
2009 public IoBuffer putPrefixedString(CharSequence in, CharsetEncoder encoder)
2010 throws CharacterCodingException {
2011 return putPrefixedString(in, 2, 0, encoder);
2012 }
2013
2014
2015
2016
2017 @Override
2018 public IoBuffer putPrefixedString(CharSequence in, int prefixLength,
2019 CharsetEncoder encoder) throws CharacterCodingException {
2020 return putPrefixedString(in, prefixLength, 0, encoder);
2021 }
2022
2023
2024
2025
2026 @Override
2027 public IoBuffer putPrefixedString(CharSequence in, int prefixLength,
2028 int padding, CharsetEncoder encoder)
2029 throws CharacterCodingException {
2030 return putPrefixedString(in, prefixLength, padding, (byte) 0, encoder);
2031 }
2032
2033
2034
2035
2036 @Override
2037 public IoBuffer putPrefixedString(CharSequence val, int prefixLength,
2038 int padding, byte padValue, CharsetEncoder encoder)
2039 throws CharacterCodingException {
2040 int maxLength;
2041 switch (prefixLength) {
2042 case 1:
2043 maxLength = 255;
2044 break;
2045 case 2:
2046 maxLength = 65535;
2047 break;
2048 case 4:
2049 maxLength = Integer.MAX_VALUE;
2050 break;
2051 default:
2052 throw new IllegalArgumentException("prefixLength: " + prefixLength);
2053 }
2054
2055 if (val.length() > maxLength) {
2056 throw new IllegalArgumentException(
2057 "The specified string is too long.");
2058 }
2059 if (val.length() == 0) {
2060 switch (prefixLength) {
2061 case 1:
2062 put((byte) 0);
2063 break;
2064 case 2:
2065 putShort((short) 0);
2066 break;
2067 case 4:
2068 putInt(0);
2069 break;
2070 }
2071 return this;
2072 }
2073
2074 int padMask;
2075 switch (padding) {
2076 case 0:
2077 case 1:
2078 padMask = 0;
2079 break;
2080 case 2:
2081 padMask = 1;
2082 break;
2083 case 4:
2084 padMask = 3;
2085 break;
2086 default:
2087 throw new IllegalArgumentException("padding: " + padding);
2088 }
2089
2090 CharBuffer in = CharBuffer.wrap(val);
2091 skip(prefixLength);
2092 int oldPos = position();
2093 encoder.reset();
2094
2095 int expandedState = 0;
2096
2097 for (;;) {
2098 CoderResult cr;
2099 if (in.hasRemaining()) {
2100 cr = encoder.encode(in, buf(), true);
2101 } else {
2102 cr = encoder.flush(buf());
2103 }
2104
2105 if (position() - oldPos > maxLength) {
2106 throw new IllegalArgumentException(
2107 "The specified string is too long.");
2108 }
2109
2110 if (cr.isUnderflow()) {
2111 break;
2112 }
2113 if (cr.isOverflow()) {
2114 if (isAutoExpand()) {
2115 switch (expandedState) {
2116 case 0:
2117 autoExpand((int) Math.ceil(in.remaining()
2118 * encoder.averageBytesPerChar()));
2119 expandedState++;
2120 break;
2121 case 1:
2122 autoExpand((int) Math.ceil(in.remaining()
2123 * encoder.maxBytesPerChar()));
2124 expandedState++;
2125 break;
2126 default:
2127 throw new RuntimeException("Expanded by "
2128 + (int) Math.ceil(in.remaining()
2129 * encoder.maxBytesPerChar())
2130 + " but that wasn't enough for '" + val + "'");
2131 }
2132 continue;
2133 }
2134 } else {
2135 expandedState = 0;
2136 }
2137 cr.throwException();
2138 }
2139
2140
2141 fill(padValue, padding - (position() - oldPos & padMask));
2142 int length = position() - oldPos;
2143 switch (prefixLength) {
2144 case 1:
2145 put(oldPos - 1, (byte) length);
2146 break;
2147 case 2:
2148 putShort(oldPos - 2, (short) length);
2149 break;
2150 case 4:
2151 putInt(oldPos - 4, length);
2152 break;
2153 }
2154 return this;
2155 }
2156
2157
2158
2159
2160 @Override
2161 public Object getObject() throws ClassNotFoundException {
2162 return getObject(Thread.currentThread().getContextClassLoader());
2163 }
2164
2165
2166
2167
2168 @Override
2169 public Object getObject(final ClassLoader classLoader)
2170 throws ClassNotFoundException {
2171 if (!prefixedDataAvailable(4)) {
2172 throw new BufferUnderflowException();
2173 }
2174
2175 int length = getInt();
2176 if (length <= 4) {
2177 throw new BufferDataException(
2178 "Object length should be greater than 4: " + length);
2179 }
2180
2181 int oldLimit = limit();
2182 limit(position() + length);
2183 try {
2184 ObjectInputStream in = new ObjectInputStream(asInputStream()) {
2185 @Override
2186 protected ObjectStreamClass readClassDescriptor()
2187 throws IOException, ClassNotFoundException {
2188 int type = read();
2189 if (type < 0) {
2190 throw new EOFException();
2191 }
2192 switch (type) {
2193 case 0:
2194 return super.readClassDescriptor();
2195 case 1:
2196 String className = readUTF();
2197 Class<?> clazz = Class.forName(className, true,
2198 classLoader);
2199 return ObjectStreamClass.lookup(clazz);
2200 default:
2201 throw new StreamCorruptedException(
2202 "Unexpected class descriptor type: " + type);
2203 }
2204 }
2205
2206 @Override
2207 protected Class<?> resolveClass(ObjectStreamClass desc)
2208 throws IOException, ClassNotFoundException {
2209 String name = desc.getName();
2210 try {
2211 return Class.forName(name, false, classLoader);
2212 } catch (ClassNotFoundException ex) {
2213 return super.resolveClass(desc);
2214 }
2215 }
2216 };
2217 return in.readObject();
2218 } catch (IOException e) {
2219 throw new BufferDataException(e);
2220 } finally {
2221 limit(oldLimit);
2222 }
2223 }
2224
2225
2226
2227
2228 @Override
2229 public IoBuffer putObject(Object o) {
2230 int oldPos = position();
2231 skip(4);
2232 try {
2233 ObjectOutputStream out = new ObjectOutputStream(asOutputStream()) {
2234 @Override
2235 protected void writeClassDescriptor(ObjectStreamClass desc)
2236 throws IOException {
2237 try {
2238 Class<?> clz = Class.forName(desc.getName());
2239 if (!Serializable.class.isAssignableFrom(clz)) {
2240 write(0);
2241 super.writeClassDescriptor(desc);
2242 } else {
2243 write(1);
2244 writeUTF(desc.getName());
2245 }
2246 }
2247 catch (ClassNotFoundException ex) {
2248 write(0);
2249 super.writeClassDescriptor(desc);
2250 }
2251 }
2252 };
2253 out.writeObject(o);
2254 out.flush();
2255 } catch (IOException e) {
2256 throw new BufferDataException(e);
2257 }
2258
2259
2260 int newPos = position();
2261 position(oldPos);
2262 putInt(newPos - oldPos - 4);
2263 position(newPos);
2264 return this;
2265 }
2266
2267
2268
2269
2270 @Override
2271 public boolean prefixedDataAvailable(int prefixLength) {
2272 return prefixedDataAvailable(prefixLength, Integer.MAX_VALUE);
2273 }
2274
2275
2276
2277
2278 @Override
2279 public boolean prefixedDataAvailable(int prefixLength, int maxDataLength) {
2280 if (remaining() < prefixLength) {
2281 return false;
2282 }
2283
2284 int dataLength;
2285 switch (prefixLength) {
2286 case 1:
2287 dataLength = getUnsigned(position());
2288 break;
2289 case 2:
2290 dataLength = getUnsignedShort(position());
2291 break;
2292 case 4:
2293 dataLength = getInt(position());
2294 break;
2295 default:
2296 throw new IllegalArgumentException("prefixLength: " + prefixLength);
2297 }
2298
2299 if (dataLength < 0 || dataLength > maxDataLength) {
2300 throw new BufferDataException("dataLength: " + dataLength);
2301 }
2302
2303 return remaining() - prefixLength >= dataLength;
2304 }
2305
2306
2307
2308
2309 @Override
2310 public int indexOf(byte b) {
2311 if (hasArray()) {
2312 int arrayOffset = arrayOffset();
2313 int beginPos = arrayOffset + position();
2314 int limit = arrayOffset + limit();
2315 byte[] array = array();
2316
2317 for (int i = beginPos; i < limit; i++) {
2318 if (array[i] == b) {
2319 return i - arrayOffset;
2320 }
2321 }
2322 } else {
2323 int beginPos = position();
2324 int limit = limit();
2325
2326 for (int i = beginPos; i < limit; i++) {
2327 if (get(i) == b) {
2328 return i;
2329 }
2330 }
2331 }
2332
2333 return -1;
2334 }
2335
2336
2337
2338
2339 @Override
2340 public IoBuffer skip(int size) {
2341 autoExpand(size);
2342 return position(position() + size);
2343 }
2344
2345
2346
2347
2348 @Override
2349 public IoBuffer fill(byte value, int size) {
2350 autoExpand(size);
2351 int q = size >>> 3;
2352 int r = size & 7;
2353
2354 if (q > 0) {
2355 int intValue = value | value << 8 | value << 16 | value << 24;
2356 long longValue = intValue;
2357 longValue <<= 32;
2358 longValue |= intValue;
2359
2360 for (int i = q; i > 0; i--) {
2361 putLong(longValue);
2362 }
2363 }
2364
2365 q = r >>> 2;
2366 r = r & 3;
2367
2368 if (q > 0) {
2369 int intValue = value | value << 8 | value << 16 | value << 24;
2370 putInt(intValue);
2371 }
2372
2373 q = r >> 1;
2374 r = r & 1;
2375
2376 if (q > 0) {
2377 short shortValue = (short) (value | value << 8);
2378 putShort(shortValue);
2379 }
2380
2381 if (r > 0) {
2382 put(value);
2383 }
2384
2385 return this;
2386 }
2387
2388
2389
2390
2391 @Override
2392 public IoBuffer fillAndReset(byte value, int size) {
2393 autoExpand(size);
2394 int pos = position();
2395 try {
2396 fill(value, size);
2397 } finally {
2398 position(pos);
2399 }
2400 return this;
2401 }
2402
2403
2404
2405
2406 @Override
2407 public IoBuffer fill(int size) {
2408 autoExpand(size);
2409 int q = size >>> 3;
2410 int r = size & 7;
2411
2412 for (int i = q; i > 0; i--) {
2413 putLong(0L);
2414 }
2415
2416 q = r >>> 2;
2417 r = r & 3;
2418
2419 if (q > 0) {
2420 putInt(0);
2421 }
2422
2423 q = r >> 1;
2424 r = r & 1;
2425
2426 if (q > 0) {
2427 putShort((short) 0);
2428 }
2429
2430 if (r > 0) {
2431 put((byte) 0);
2432 }
2433
2434 return this;
2435 }
2436
2437
2438
2439
2440 @Override
2441 public IoBuffer fillAndReset(int size) {
2442 autoExpand(size);
2443 int pos = position();
2444 try {
2445 fill(size);
2446 } finally {
2447 position(pos);
2448 }
2449
2450 return this;
2451 }
2452
2453
2454
2455
2456 @Override
2457 public <E extends Enum<E>> E getEnum(Class<E> enumClass) {
2458 return toEnum(enumClass, getUnsigned());
2459 }
2460
2461
2462
2463
2464 @Override
2465 public <E extends Enum<E>> E getEnum(int index, Class<E> enumClass) {
2466 return toEnum(enumClass, getUnsigned(index));
2467 }
2468
2469
2470
2471
2472 @Override
2473 public <E extends Enum<E>> E getEnumShort(Class<E> enumClass) {
2474 return toEnum(enumClass, getUnsignedShort());
2475 }
2476
2477
2478
2479
2480 @Override
2481 public <E extends Enum<E>> E getEnumShort(int index, Class<E> enumClass) {
2482 return toEnum(enumClass, getUnsignedShort(index));
2483 }
2484
2485
2486
2487
2488 @Override
2489 public <E extends Enum<E>> E getEnumInt(Class<E> enumClass) {
2490 return toEnum(enumClass, getInt());
2491 }
2492
2493
2494
2495
2496 public <E extends Enum<E>> E getEnumInt(int index, Class<E> enumClass) {
2497 return toEnum(enumClass, getInt(index));
2498 }
2499
2500
2501
2502
2503 @Override
2504 public IoBuffer putEnum(Enum<?> e) {
2505 if (e.ordinal() > BYTE_MASK) {
2506 throw new IllegalArgumentException(enumConversionErrorMessage(e,
2507 "byte"));
2508 }
2509 return put((byte) e.ordinal());
2510 }
2511
2512
2513
2514
2515 @Override
2516 public IoBuffer putEnum(int index, Enum<?> e) {
2517 if (e.ordinal() > BYTE_MASK) {
2518 throw new IllegalArgumentException(enumConversionErrorMessage(e,
2519 "byte"));
2520 }
2521 return put(index, (byte) e.ordinal());
2522 }
2523
2524
2525
2526
2527 @Override
2528 public IoBuffer putEnumShort(Enum<?> e) {
2529 if (e.ordinal() > SHORT_MASK) {
2530 throw new IllegalArgumentException(enumConversionErrorMessage(e,
2531 "short"));
2532 }
2533 return putShort((short) e.ordinal());
2534 }
2535
2536
2537
2538
2539 @Override
2540 public IoBuffer putEnumShort(int index, Enum<?> e) {
2541 if (e.ordinal() > SHORT_MASK) {
2542 throw new IllegalArgumentException(enumConversionErrorMessage(e,
2543 "short"));
2544 }
2545 return putShort(index, (short) e.ordinal());
2546 }
2547
2548
2549
2550
2551 @Override
2552 public IoBuffer putEnumInt(Enum<?> e) {
2553 return putInt(e.ordinal());
2554 }
2555
2556
2557
2558
2559 @Override
2560 public IoBuffer putEnumInt(int index, Enum<?> e) {
2561 return putInt(index, e.ordinal());
2562 }
2563
2564 private <E> E toEnum(Class<E> enumClass, int i) {
2565 E[] enumConstants = enumClass.getEnumConstants();
2566 if (i > enumConstants.length) {
2567 throw new IndexOutOfBoundsException(String.format(
2568 "%d is too large of an ordinal to convert to the enum %s",
2569 i, enumClass.getName()));
2570 }
2571 return enumConstants[i];
2572 }
2573
2574 private String enumConversionErrorMessage(Enum<?> e, String type) {
2575 return String.format("%s.%s has an ordinal value too large for a %s", e
2576 .getClass().getName(), e.name(), type);
2577 }
2578
2579
2580
2581
2582 @Override
2583 public <E extends Enum<E>> EnumSet<E> getEnumSet(Class<E> enumClass) {
2584 return toEnumSet(enumClass, get() & BYTE_MASK);
2585 }
2586
2587
2588
2589
2590 @Override
2591 public <E extends Enum<E>> EnumSet<E> getEnumSet(int index,
2592 Class<E> enumClass) {
2593 return toEnumSet(enumClass, get(index) & BYTE_MASK);
2594 }
2595
2596
2597
2598
2599 @Override
2600 public <E extends Enum<E>> EnumSet<E> getEnumSetShort(Class<E> enumClass) {
2601 return toEnumSet(enumClass, getShort() & SHORT_MASK);
2602 }
2603
2604
2605
2606
2607 @Override
2608 public <E extends Enum<E>> EnumSet<E> getEnumSetShort(int index,
2609 Class<E> enumClass) {
2610 return toEnumSet(enumClass, getShort(index) & SHORT_MASK);
2611 }
2612
2613
2614
2615
2616 @Override
2617 public <E extends Enum<E>> EnumSet<E> getEnumSetInt(Class<E> enumClass) {
2618 return toEnumSet(enumClass, getInt() & INT_MASK);
2619 }
2620
2621
2622
2623
2624 @Override
2625 public <E extends Enum<E>> EnumSet<E> getEnumSetInt(int index,
2626 Class<E> enumClass) {
2627 return toEnumSet(enumClass, getInt(index) & INT_MASK);
2628 }
2629
2630
2631
2632
2633 @Override
2634 public <E extends Enum<E>> EnumSet<E> getEnumSetLong(Class<E> enumClass) {
2635 return toEnumSet(enumClass, getLong());
2636 }
2637
2638
2639
2640
2641 @Override
2642 public <E extends Enum<E>> EnumSet<E> getEnumSetLong(int index,
2643 Class<E> enumClass) {
2644 return toEnumSet(enumClass, getLong(index));
2645 }
2646
2647 private <E extends Enum<E>> EnumSet<E> toEnumSet(Class<E> clazz, long vector) {
2648 EnumSet<E> set = EnumSet.noneOf(clazz);
2649 long mask = 1;
2650 for (E e : clazz.getEnumConstants()) {
2651 if ((mask & vector) == mask) {
2652 set.add(e);
2653 }
2654 mask <<= 1;
2655 }
2656 return set;
2657 }
2658
2659
2660
2661
2662 @Override
2663 public <E extends Enum<E>> IoBuffer putEnumSet(Set<E> set) {
2664 long vector = toLong(set);
2665 if ((vector & ~BYTE_MASK) != 0) {
2666 throw new IllegalArgumentException(
2667 "The enum set is too large to fit in a byte: " + set);
2668 }
2669 return put((byte) vector);
2670 }
2671
2672
2673
2674
2675 @Override
2676 public <E extends Enum<E>> IoBuffer putEnumSet(int index, Set<E> set) {
2677 long vector = toLong(set);
2678 if ((vector & ~BYTE_MASK) != 0) {
2679 throw new IllegalArgumentException(
2680 "The enum set is too large to fit in a byte: " + set);
2681 }
2682 return put(index, (byte) vector);
2683 }
2684
2685
2686
2687
2688 @Override
2689 public <E extends Enum<E>> IoBuffer putEnumSetShort(Set<E> set) {
2690 long vector = toLong(set);
2691 if ((vector & ~SHORT_MASK) != 0) {
2692 throw new IllegalArgumentException(
2693 "The enum set is too large to fit in a short: " + set);
2694 }
2695 return putShort((short) vector);
2696 }
2697
2698
2699
2700
2701 @Override
2702 public <E extends Enum<E>> IoBuffer putEnumSetShort(int index, Set<E> set) {
2703 long vector = toLong(set);
2704 if ((vector & ~SHORT_MASK) != 0) {
2705 throw new IllegalArgumentException(
2706 "The enum set is too large to fit in a short: " + set);
2707 }
2708 return putShort(index, (short) vector);
2709 }
2710
2711
2712
2713
2714 @Override
2715 public <E extends Enum<E>> IoBuffer putEnumSetInt(Set<E> set) {
2716 long vector = toLong(set);
2717 if ((vector & ~INT_MASK) != 0) {
2718 throw new IllegalArgumentException(
2719 "The enum set is too large to fit in an int: " + set);
2720 }
2721 return putInt((int) vector);
2722 }
2723
2724
2725
2726
2727 @Override
2728 public <E extends Enum<E>> IoBuffer putEnumSetInt(int index, Set<E> set) {
2729 long vector = toLong(set);
2730 if ((vector & ~INT_MASK) != 0) {
2731 throw new IllegalArgumentException(
2732 "The enum set is too large to fit in an int: " + set);
2733 }
2734 return putInt(index, (int) vector);
2735 }
2736
2737
2738
2739
2740 @Override
2741 public <E extends Enum<E>> IoBuffer putEnumSetLong(Set<E> set) {
2742 return putLong(toLong(set));
2743 }
2744
2745
2746
2747
2748 @Override
2749 public <E extends Enum<E>> IoBuffer putEnumSetLong(int index, Set<E> set) {
2750 return putLong(index, toLong(set));
2751 }
2752
2753 private <E extends Enum<E>> long toLong(Set<E> set) {
2754 long vector = 0;
2755 for (E e : set) {
2756 if (e.ordinal() >= Long.SIZE) {
2757 throw new IllegalArgumentException(
2758 "The enum set is too large to fit in a bit vector: "
2759 + set);
2760 }
2761 vector |= 1L << e.ordinal();
2762 }
2763 return vector;
2764 }
2765
2766
2767
2768
2769
2770 private IoBuffer autoExpand(int expectedRemaining) {
2771 if (isAutoExpand()) {
2772 expand(expectedRemaining, true);
2773 }
2774 return this;
2775 }
2776
2777
2778
2779
2780
2781 private IoBuffer autoExpand(int pos, int expectedRemaining) {
2782 if (isAutoExpand()) {
2783 expand(pos, expectedRemaining, true);
2784 }
2785 return this;
2786 }
2787
2788 private static void checkFieldSize(int fieldSize) {
2789 if (fieldSize < 0) {
2790 throw new IllegalArgumentException("fieldSize cannot be negative: "
2791 + fieldSize);
2792 }
2793 }
2794 }