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