1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 package org.jboss.netty.buffer;
17
18 import org.jboss.netty.util.CharsetUtil;
19
20 import java.nio.ByteBuffer;
21 import java.nio.ByteOrder;
22 import java.nio.CharBuffer;
23 import java.nio.charset.CharacterCodingException;
24 import java.nio.charset.Charset;
25 import java.nio.charset.CharsetDecoder;
26 import java.nio.charset.CharsetEncoder;
27 import java.nio.charset.CoderResult;
28 import java.util.ArrayList;
29 import java.util.List;
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88 public final class ChannelBuffers {
89
90
91
92
93 public static final ByteOrder BIG_ENDIAN = ByteOrder.BIG_ENDIAN;
94
95
96
97
98 public static final ByteOrder LITTLE_ENDIAN = ByteOrder.LITTLE_ENDIAN;
99
100
101
102
103 public static final ChannelBuffer EMPTY_BUFFER = new BigEndianHeapChannelBuffer(0);
104
105 private static final char[] HEXDUMP_TABLE = new char[256 * 4];
106
107 static {
108 final char[] DIGITS = "0123456789abcdef".toCharArray();
109 for (int i = 0; i < 256; i ++) {
110 HEXDUMP_TABLE[i << 1] = DIGITS[i >>> 4 & 0x0F];
111 HEXDUMP_TABLE[(i << 1) + 1] = DIGITS[i & 0x0F];
112 }
113 }
114
115
116
117
118
119
120 public static ChannelBuffer buffer(int capacity) {
121 return buffer(BIG_ENDIAN, capacity);
122 }
123
124
125
126
127
128
129 public static ChannelBuffer buffer(ByteOrder endianness, int capacity) {
130 if (endianness == BIG_ENDIAN) {
131 if (capacity == 0) {
132 return EMPTY_BUFFER;
133 }
134 return new BigEndianHeapChannelBuffer(capacity);
135 } else if (endianness == LITTLE_ENDIAN) {
136 if (capacity == 0) {
137 return EMPTY_BUFFER;
138 }
139 return new LittleEndianHeapChannelBuffer(capacity);
140 } else {
141 throw new NullPointerException("endianness");
142 }
143 }
144
145
146
147
148
149
150 public static ChannelBuffer directBuffer(int capacity) {
151 return directBuffer(BIG_ENDIAN, capacity);
152 }
153
154
155
156
157
158
159 public static ChannelBuffer directBuffer(ByteOrder endianness, int capacity) {
160 if (endianness == null) {
161 throw new NullPointerException("endianness");
162 }
163 if (capacity == 0) {
164 return EMPTY_BUFFER;
165 }
166
167 ChannelBuffer buffer = new ByteBufferBackedChannelBuffer(
168 ByteBuffer.allocateDirect(capacity).order(endianness));
169 buffer.clear();
170 return buffer;
171 }
172
173
174
175
176
177
178 public static ChannelBuffer dynamicBuffer() {
179 return dynamicBuffer(BIG_ENDIAN, 256);
180 }
181
182 public static ChannelBuffer dynamicBuffer(ChannelBufferFactory factory) {
183 if (factory == null) {
184 throw new NullPointerException("factory");
185 }
186
187 return new DynamicChannelBuffer(factory.getDefaultOrder(), 256, factory);
188 }
189
190
191
192
193
194
195
196 public static ChannelBuffer dynamicBuffer(int estimatedLength) {
197 return dynamicBuffer(BIG_ENDIAN, estimatedLength);
198 }
199
200
201
202
203
204
205
206 public static ChannelBuffer dynamicBuffer(ByteOrder endianness, int estimatedLength) {
207 return new DynamicChannelBuffer(endianness, estimatedLength);
208 }
209
210
211
212
213
214
215
216 public static ChannelBuffer dynamicBuffer(int estimatedLength, ChannelBufferFactory factory) {
217 if (factory == null) {
218 throw new NullPointerException("factory");
219 }
220
221 return new DynamicChannelBuffer(factory.getDefaultOrder(), estimatedLength, factory);
222 }
223
224
225
226
227
228
229
230 public static ChannelBuffer dynamicBuffer(
231 ByteOrder endianness, int estimatedLength, ChannelBufferFactory factory) {
232 return new DynamicChannelBuffer(endianness, estimatedLength, factory);
233 }
234
235
236
237
238
239
240 public static ChannelBuffer wrappedBuffer(byte[] array) {
241 return wrappedBuffer(BIG_ENDIAN, array);
242 }
243
244
245
246
247
248
249 public static ChannelBuffer wrappedBuffer(ByteOrder endianness, byte[] array) {
250 if (endianness == BIG_ENDIAN) {
251 if (array.length == 0) {
252 return EMPTY_BUFFER;
253 }
254 return new BigEndianHeapChannelBuffer(array);
255 } else if (endianness == LITTLE_ENDIAN) {
256 if (array.length == 0) {
257 return EMPTY_BUFFER;
258 }
259 return new LittleEndianHeapChannelBuffer(array);
260 } else {
261 throw new NullPointerException("endianness");
262 }
263 }
264
265
266
267
268
269
270 public static ChannelBuffer wrappedBuffer(byte[] array, int offset, int length) {
271 return wrappedBuffer(BIG_ENDIAN, array, offset, length);
272 }
273
274
275
276
277
278
279 public static ChannelBuffer wrappedBuffer(ByteOrder endianness, byte[] array, int offset, int length) {
280 if (endianness == null) {
281 throw new NullPointerException("endianness");
282 }
283 if (offset == 0) {
284 if (length == array.length) {
285 return wrappedBuffer(endianness, array);
286 } else {
287 if (length == 0) {
288 return EMPTY_BUFFER;
289 } else {
290 return new TruncatedChannelBuffer(wrappedBuffer(endianness, array), length);
291 }
292 }
293 } else {
294 if (length == 0) {
295 return EMPTY_BUFFER;
296 } else {
297 return new SlicedChannelBuffer(wrappedBuffer(endianness, array), offset, length);
298 }
299 }
300 }
301
302
303
304
305
306
307 public static ChannelBuffer wrappedBuffer(ByteBuffer buffer) {
308 if (!buffer.hasRemaining()) {
309 return EMPTY_BUFFER;
310 }
311 if (buffer.hasArray()) {
312 return wrappedBuffer(
313 buffer.order(), buffer.array(), buffer.arrayOffset() + buffer.position(), buffer.remaining());
314 } else {
315 return new ByteBufferBackedChannelBuffer(buffer);
316 }
317 }
318
319
320
321
322
323
324 public static ChannelBuffer wrappedBuffer(ChannelBuffer buffer) {
325 if (buffer.readable()) {
326 return buffer.slice();
327 } else {
328 return EMPTY_BUFFER;
329 }
330 }
331
332
333
334
335
336
337 public static ChannelBuffer wrappedBuffer(byte[]... arrays) {
338 return wrappedBuffer(BIG_ENDIAN, arrays);
339 }
340
341
342
343
344
345
346
347
348 public static ChannelBuffer wrappedBuffer(ByteOrder endianness, byte[]... arrays) {
349 switch (arrays.length) {
350 case 0:
351 break;
352 case 1:
353 if (arrays[0].length != 0) {
354 return wrappedBuffer(endianness, arrays[0]);
355 }
356 break;
357 default:
358
359 final List<ChannelBuffer> components = new ArrayList<ChannelBuffer>(arrays.length);
360 for (byte[] a: arrays) {
361 if (a == null) {
362 break;
363 }
364 if (a.length > 0) {
365 components.add(wrappedBuffer(endianness, a));
366 }
367 }
368 return compositeBuffer(endianness, components, false);
369 }
370
371 return EMPTY_BUFFER;
372 }
373
374 private static ChannelBuffer compositeBuffer(
375 ByteOrder endianness, List<ChannelBuffer> components, boolean gathering) {
376 switch (components.size()) {
377 case 0:
378 return EMPTY_BUFFER;
379 case 1:
380 return components.get(0);
381 default:
382 return new CompositeChannelBuffer(endianness, components, gathering);
383 }
384 }
385
386
387
388
389
390
391
392
393
394
395 public static ChannelBuffer wrappedBuffer(ChannelBuffer... buffers) {
396 return wrappedBuffer(false, buffers);
397 }
398
399
400
401
402
403
404
405
406
407
408
409 public static ChannelBuffer wrappedBuffer(boolean gathering, ChannelBuffer... buffers) {
410 switch (buffers.length) {
411 case 0:
412 break;
413 case 1:
414 if (buffers[0].readable()) {
415 return wrappedBuffer(buffers[0]);
416 }
417 break;
418 default:
419 ByteOrder order = null;
420 final List<ChannelBuffer> components = new ArrayList<ChannelBuffer>(buffers.length);
421 for (ChannelBuffer c: buffers) {
422 if (c == null) {
423 break;
424 }
425 if (c.readable()) {
426 if (order != null) {
427 if (!order.equals(c.order())) {
428 throw new IllegalArgumentException(
429 "inconsistent byte order");
430 }
431 } else {
432 order = c.order();
433 }
434 if (c instanceof CompositeChannelBuffer) {
435
436 components.addAll(
437 ((CompositeChannelBuffer) c).decompose(
438 c.readerIndex(), c.readableBytes()));
439 } else {
440
441 components.add(c.slice());
442 }
443 }
444 }
445 return compositeBuffer(order, components, gathering);
446 }
447 return EMPTY_BUFFER;
448 }
449
450
451
452
453
454
455
456
457
458
459
460 public static ChannelBuffer wrappedBuffer(ByteBuffer... buffers) {
461 return wrappedBuffer(false, buffers);
462 }
463
464
465
466
467
468
469
470
471
472
473
474
475 public static ChannelBuffer wrappedBuffer(boolean gathering, ByteBuffer... buffers) {
476 switch (buffers.length) {
477 case 0:
478 break;
479 case 1:
480 if (buffers[0].hasRemaining()) {
481 return wrappedBuffer(buffers[0]);
482 }
483 break;
484 default:
485 ByteOrder order = null;
486 final List<ChannelBuffer> components = new ArrayList<ChannelBuffer>(buffers.length);
487 for (ByteBuffer b: buffers) {
488 if (b == null) {
489 break;
490 }
491 if (b.hasRemaining()) {
492 if (order != null) {
493 if (!order.equals(b.order())) {
494 throw new IllegalArgumentException(
495 "inconsistent byte order");
496 }
497 } else {
498 order = b.order();
499 }
500 components.add(wrappedBuffer(b));
501 }
502 }
503 return compositeBuffer(order, components, gathering);
504 }
505
506 return EMPTY_BUFFER;
507 }
508
509
510
511
512
513
514 public static ChannelBuffer copiedBuffer(byte[] array) {
515 return copiedBuffer(BIG_ENDIAN, array);
516 }
517
518
519
520
521
522
523
524 public static ChannelBuffer copiedBuffer(ByteOrder endianness, byte[] array) {
525 if (endianness == BIG_ENDIAN) {
526 if (array.length == 0) {
527 return EMPTY_BUFFER;
528 }
529 return new BigEndianHeapChannelBuffer(array.clone());
530 } else if (endianness == LITTLE_ENDIAN) {
531 if (array.length == 0) {
532 return EMPTY_BUFFER;
533 }
534 return new LittleEndianHeapChannelBuffer(array.clone());
535 } else {
536 throw new NullPointerException("endianness");
537 }
538 }
539
540
541
542
543
544
545
546 public static ChannelBuffer copiedBuffer(byte[] array, int offset, int length) {
547 return copiedBuffer(BIG_ENDIAN, array, offset, length);
548 }
549
550
551
552
553
554
555
556 public static ChannelBuffer copiedBuffer(ByteOrder endianness, byte[] array, int offset, int length) {
557 if (endianness == null) {
558 throw new NullPointerException("endianness");
559 }
560 if (length == 0) {
561 return EMPTY_BUFFER;
562 }
563 byte[] copy = new byte[length];
564 System.arraycopy(array, offset, copy, 0, length);
565 return wrappedBuffer(endianness, copy);
566 }
567
568
569
570
571
572
573
574 public static ChannelBuffer copiedBuffer(ByteBuffer buffer) {
575 int length = buffer.remaining();
576 if (length == 0) {
577 return EMPTY_BUFFER;
578 }
579 byte[] copy = new byte[length];
580 int position = buffer.position();
581 try {
582 buffer.get(copy);
583 } finally {
584 buffer.position(position);
585 }
586 return wrappedBuffer(buffer.order(), copy);
587 }
588
589
590
591
592
593
594
595 public static ChannelBuffer copiedBuffer(ChannelBuffer buffer) {
596 if (buffer.readable()) {
597 return buffer.copy();
598 } else {
599 return EMPTY_BUFFER;
600 }
601 }
602
603
604
605
606
607
608
609 public static ChannelBuffer copiedBuffer(byte[]... arrays) {
610 return copiedBuffer(BIG_ENDIAN, arrays);
611 }
612
613
614
615
616
617
618
619 public static ChannelBuffer copiedBuffer(ByteOrder endianness, byte[]... arrays) {
620 switch (arrays.length) {
621 case 0:
622 return EMPTY_BUFFER;
623 case 1:
624 if (arrays[0].length == 0) {
625 return EMPTY_BUFFER;
626 } else {
627 return copiedBuffer(endianness, arrays[0]);
628 }
629 }
630
631
632 int length = 0;
633 for (byte[] a: arrays) {
634 if (Integer.MAX_VALUE - length < a.length) {
635 throw new IllegalArgumentException(
636 "The total length of the specified arrays is too big.");
637 }
638 length += a.length;
639 }
640
641 if (length == 0) {
642 return EMPTY_BUFFER;
643 }
644
645 byte[] mergedArray = new byte[length];
646 for (int i = 0, j = 0; i < arrays.length; i ++) {
647 byte[] a = arrays[i];
648 System.arraycopy(a, 0, mergedArray, j, a.length);
649 j += a.length;
650 }
651
652 return wrappedBuffer(endianness, mergedArray);
653 }
654
655
656
657
658
659
660
661
662
663
664
665 public static ChannelBuffer copiedBuffer(ChannelBuffer... buffers) {
666 switch (buffers.length) {
667 case 0:
668 return EMPTY_BUFFER;
669 case 1:
670 return copiedBuffer(buffers[0]);
671 }
672
673 ChannelBuffer[] copiedBuffers = new ChannelBuffer[buffers.length];
674 for (int i = 0; i < buffers.length; i ++) {
675 copiedBuffers[i] = copiedBuffer(buffers[i]);
676 }
677 return wrappedBuffer(false, copiedBuffers);
678 }
679
680
681
682
683
684
685
686
687
688
689
690 public static ChannelBuffer copiedBuffer(ByteBuffer... buffers) {
691 switch (buffers.length) {
692 case 0:
693 return EMPTY_BUFFER;
694 case 1:
695 return copiedBuffer(buffers[0]);
696 }
697
698 ChannelBuffer[] copiedBuffers = new ChannelBuffer[buffers.length];
699 for (int i = 0; i < buffers.length; i ++) {
700 copiedBuffers[i] = copiedBuffer(buffers[i]);
701 }
702 return wrappedBuffer(false, copiedBuffers);
703 }
704
705
706
707
708
709
710
711 public static ChannelBuffer copiedBuffer(CharSequence string, Charset charset) {
712 return copiedBuffer(BIG_ENDIAN, string, charset);
713 }
714
715
716
717
718
719
720
721 public static ChannelBuffer copiedBuffer(
722 CharSequence string, int offset, int length, Charset charset) {
723 return copiedBuffer(BIG_ENDIAN, string, offset, length, charset);
724 }
725
726
727
728
729
730
731
732
733 public static ChannelBuffer copiedBuffer(ByteOrder endianness, CharSequence string, Charset charset) {
734 if (string == null) {
735 throw new NullPointerException("string");
736 }
737
738 if (string instanceof CharBuffer) {
739 return copiedBuffer(endianness, (CharBuffer) string, charset);
740 }
741
742 return copiedBuffer(endianness, CharBuffer.wrap(string), charset);
743 }
744
745
746
747
748
749
750
751
752 public static ChannelBuffer copiedBuffer(
753 ByteOrder endianness, CharSequence string, int offset, int length, Charset charset) {
754 if (string == null) {
755 throw new NullPointerException("string");
756 }
757 if (length == 0) {
758 return EMPTY_BUFFER;
759 }
760
761 if (string instanceof CharBuffer) {
762 CharBuffer buf = (CharBuffer) string;
763 if (buf.hasArray()) {
764 return copiedBuffer(
765 endianness,
766 buf.array(),
767 buf.arrayOffset() + buf.position() + offset,
768 length, charset);
769 }
770
771 buf = buf.slice();
772 buf.limit(length);
773 buf.position(offset);
774 return copiedBuffer(endianness, buf, charset);
775 }
776
777 return copiedBuffer(
778 endianness, CharBuffer.wrap(string, offset, offset + length),
779 charset);
780 }
781
782
783
784
785
786
787
788 public static ChannelBuffer copiedBuffer(char[] array, Charset charset) {
789 return copiedBuffer(BIG_ENDIAN, array, 0, array.length, charset);
790 }
791
792
793
794
795
796
797
798 public static ChannelBuffer copiedBuffer(
799 char[] array, int offset, int length, Charset charset) {
800 return copiedBuffer(BIG_ENDIAN, array, offset, length, charset);
801 }
802
803
804
805
806
807
808
809
810 public static ChannelBuffer copiedBuffer(ByteOrder endianness, char[] array, Charset charset) {
811 return copiedBuffer(endianness, array, 0, array.length, charset);
812 }
813
814
815
816
817
818
819
820
821 public static ChannelBuffer copiedBuffer(
822 ByteOrder endianness, char[] array, int offset, int length, Charset charset) {
823 if (array == null) {
824 throw new NullPointerException("array");
825 }
826 if (length == 0) {
827 return EMPTY_BUFFER;
828 }
829 return copiedBuffer(
830 endianness, CharBuffer.wrap(array, offset, length), charset);
831 }
832
833 private static ChannelBuffer copiedBuffer(ByteOrder endianness, CharBuffer buffer, Charset charset) {
834 CharBuffer src = buffer;
835 ByteBuffer dst = encodeString(src, charset);
836 ChannelBuffer result = wrappedBuffer(endianness, dst.array());
837 result.writerIndex(dst.remaining());
838 return result;
839 }
840
841
842
843
844 @Deprecated
845 public static ChannelBuffer copiedBuffer(String string, String charsetName) {
846 return copiedBuffer(string, Charset.forName(charsetName));
847 }
848
849
850
851
852 @Deprecated
853 public static ChannelBuffer copiedBuffer(ByteOrder endianness, String string, String charsetName) {
854 return copiedBuffer(endianness, string, Charset.forName(charsetName));
855 }
856
857
858
859
860
861
862
863 public static ChannelBuffer unmodifiableBuffer(ChannelBuffer buffer) {
864 if (buffer instanceof ReadOnlyChannelBuffer) {
865 buffer = ((ReadOnlyChannelBuffer) buffer).unwrap();
866 }
867 return new ReadOnlyChannelBuffer(buffer);
868 }
869
870
871
872
873 public static ChannelBuffer hexDump(String hexString) {
874 int len = hexString.length();
875 byte[] hexData = new byte[len / 2];
876 for (int i = 0; i < len; i += 2) {
877 hexData[i / 2] = (byte) ((Character.digit(hexString.charAt(i), 16) << 4)
878 + Character.digit(hexString.charAt(i + 1), 16));
879 }
880 return wrappedBuffer(hexData);
881 }
882
883
884
885
886
887 public static String hexDump(ChannelBuffer buffer) {
888 return hexDump(buffer, buffer.readerIndex(), buffer.readableBytes());
889 }
890
891
892
893
894
895 public static String hexDump(ChannelBuffer buffer, int fromIndex, int length) {
896 if (length < 0) {
897 throw new IllegalArgumentException("length: " + length);
898 }
899 if (length == 0) {
900 return "";
901 }
902
903 int endIndex = fromIndex + length;
904 char[] buf = new char[length << 1];
905
906 int srcIdx = fromIndex;
907 int dstIdx = 0;
908 for (; srcIdx < endIndex; srcIdx ++, dstIdx += 2) {
909 System.arraycopy(
910 HEXDUMP_TABLE, buffer.getUnsignedByte(srcIdx) << 1,
911 buf, dstIdx, 2);
912 }
913
914 return new String(buf);
915 }
916
917
918
919
920
921 public static int hashCode(ChannelBuffer buffer) {
922 final int aLen = buffer.readableBytes();
923 final int intCount = aLen >>> 2;
924 final int byteCount = aLen & 3;
925
926 int hashCode = 1;
927 int arrayIndex = buffer.readerIndex();
928 if (buffer.order() == BIG_ENDIAN) {
929 for (int i = intCount; i > 0; i --) {
930 hashCode = 31 * hashCode + buffer.getInt(arrayIndex);
931 arrayIndex += 4;
932 }
933 } else {
934 for (int i = intCount; i > 0; i --) {
935 hashCode = 31 * hashCode + swapInt(buffer.getInt(arrayIndex));
936 arrayIndex += 4;
937 }
938 }
939
940 for (int i = byteCount; i > 0; i --) {
941 hashCode = 31 * hashCode + buffer.getByte(arrayIndex ++);
942 }
943
944 if (hashCode == 0) {
945 hashCode = 1;
946 }
947
948 return hashCode;
949 }
950
951
952
953
954
955
956 public static boolean equals(ChannelBuffer bufferA, ChannelBuffer bufferB) {
957 final int aLen = bufferA.readableBytes();
958 if (aLen != bufferB.readableBytes()) {
959 return false;
960 }
961
962 final int longCount = aLen >>> 3;
963 final int byteCount = aLen & 7;
964
965 int aIndex = bufferA.readerIndex();
966 int bIndex = bufferB.readerIndex();
967
968 if (bufferA.order() == bufferB.order()) {
969 for (int i = longCount; i > 0; i --) {
970 if (bufferA.getLong(aIndex) != bufferB.getLong(bIndex)) {
971 return false;
972 }
973 aIndex += 8;
974 bIndex += 8;
975 }
976 } else {
977 for (int i = longCount; i > 0; i --) {
978 if (bufferA.getLong(aIndex) != swapLong(bufferB.getLong(bIndex))) {
979 return false;
980 }
981 aIndex += 8;
982 bIndex += 8;
983 }
984 }
985
986 for (int i = byteCount; i > 0; i --) {
987 if (bufferA.getByte(aIndex) != bufferB.getByte(bIndex)) {
988 return false;
989 }
990 aIndex ++;
991 bIndex ++;
992 }
993
994 return true;
995 }
996
997
998
999
1000
1001 public static int compare(ChannelBuffer bufferA, ChannelBuffer bufferB) {
1002 final int aLen = bufferA.readableBytes();
1003 final int bLen = bufferB.readableBytes();
1004 final int minLength = Math.min(aLen, bLen);
1005 final int uintCount = minLength >>> 2;
1006 final int byteCount = minLength & 3;
1007
1008 int aIndex = bufferA.readerIndex();
1009 int bIndex = bufferB.readerIndex();
1010
1011 if (bufferA.order() == bufferB.order()) {
1012 for (int i = uintCount; i > 0; i --) {
1013 long va = bufferA.getUnsignedInt(aIndex);
1014 long vb = bufferB.getUnsignedInt(bIndex);
1015 if (va > vb) {
1016 return 1;
1017 } else if (va < vb) {
1018 return -1;
1019 }
1020 aIndex += 4;
1021 bIndex += 4;
1022 }
1023 } else {
1024 for (int i = uintCount; i > 0; i --) {
1025 long va = bufferA.getUnsignedInt(aIndex);
1026 long vb = swapInt(bufferB.getInt(bIndex)) & 0xFFFFFFFFL;
1027 if (va > vb) {
1028 return 1;
1029 } else if (va < vb) {
1030 return -1;
1031 }
1032 aIndex += 4;
1033 bIndex += 4;
1034 }
1035 }
1036
1037 for (int i = byteCount; i > 0; i --) {
1038 short va = bufferA.getUnsignedByte(aIndex);
1039 short vb = bufferB.getUnsignedByte(bIndex);
1040 if (va > vb) {
1041 return 1;
1042 } else if (va < vb) {
1043 return -1;
1044 }
1045 aIndex ++;
1046 bIndex ++;
1047 }
1048
1049 return aLen - bLen;
1050 }
1051
1052
1053
1054
1055
1056 public static int indexOf(ChannelBuffer buffer, int fromIndex, int toIndex, byte value) {
1057 if (fromIndex <= toIndex) {
1058 return firstIndexOf(buffer, fromIndex, toIndex, value);
1059 } else {
1060 return lastIndexOf(buffer, fromIndex, toIndex, value);
1061 }
1062 }
1063
1064
1065
1066
1067
1068 public static int indexOf(
1069 ChannelBuffer buffer, int fromIndex, int toIndex, ChannelBufferIndexFinder indexFinder) {
1070 if (fromIndex <= toIndex) {
1071 return firstIndexOf(buffer, fromIndex, toIndex, indexFinder);
1072 } else {
1073 return lastIndexOf(buffer, fromIndex, toIndex, indexFinder);
1074 }
1075 }
1076
1077
1078
1079
1080 public static short swapShort(short value) {
1081 return (short) (value << 8 | value >>> 8 & 0xff);
1082 }
1083
1084
1085
1086
1087 public static int swapMedium(int value) {
1088 return value << 16 & 0xff0000 | value & 0xff00 | value >>> 16 & 0xff;
1089 }
1090
1091
1092
1093
1094 public static int swapInt(int value) {
1095 return swapShort((short) value) << 16 |
1096 swapShort((short) (value >>> 16)) & 0xffff;
1097 }
1098
1099
1100
1101
1102 public static long swapLong(long value) {
1103 return (long) swapInt((int) value) << 32 |
1104 swapInt((int) (value >>> 32)) & 0xffffffffL;
1105 }
1106
1107 private static int firstIndexOf(ChannelBuffer buffer, int fromIndex, int toIndex, byte value) {
1108 fromIndex = Math.max(fromIndex, 0);
1109 if (fromIndex >= toIndex || buffer.capacity() == 0) {
1110 return -1;
1111 }
1112
1113 for (int i = fromIndex; i < toIndex; i ++) {
1114 if (buffer.getByte(i) == value) {
1115 return i;
1116 }
1117 }
1118
1119 return -1;
1120 }
1121
1122 private static int lastIndexOf(ChannelBuffer buffer, int fromIndex, int toIndex, byte value) {
1123 fromIndex = Math.min(fromIndex, buffer.capacity());
1124 if (fromIndex < 0 || buffer.capacity() == 0) {
1125 return -1;
1126 }
1127
1128 for (int i = fromIndex - 1; i >= toIndex; i --) {
1129 if (buffer.getByte(i) == value) {
1130 return i;
1131 }
1132 }
1133
1134 return -1;
1135 }
1136
1137 private static int firstIndexOf(
1138 ChannelBuffer buffer, int fromIndex, int toIndex, ChannelBufferIndexFinder indexFinder) {
1139 fromIndex = Math.max(fromIndex, 0);
1140 if (fromIndex >= toIndex || buffer.capacity() == 0) {
1141 return -1;
1142 }
1143
1144 for (int i = fromIndex; i < toIndex; i ++) {
1145 if (indexFinder.find(buffer, i)) {
1146 return i;
1147 }
1148 }
1149
1150 return -1;
1151 }
1152
1153 private static int lastIndexOf(
1154 ChannelBuffer buffer, int fromIndex, int toIndex, ChannelBufferIndexFinder indexFinder) {
1155 fromIndex = Math.min(fromIndex, buffer.capacity());
1156 if (fromIndex < 0 || buffer.capacity() == 0) {
1157 return -1;
1158 }
1159
1160 for (int i = fromIndex - 1; i >= toIndex; i --) {
1161 if (indexFinder.find(buffer, i)) {
1162 return i;
1163 }
1164 }
1165
1166 return -1;
1167 }
1168
1169 static ByteBuffer encodeString(CharBuffer src, Charset charset) {
1170 final CharsetEncoder encoder = CharsetUtil.getEncoder(charset);
1171 final ByteBuffer dst = ByteBuffer.allocate(
1172 (int) ((double) src.remaining() * encoder.maxBytesPerChar()));
1173 try {
1174 CoderResult cr = encoder.encode(src, dst, true);
1175 if (!cr.isUnderflow()) {
1176 cr.throwException();
1177 }
1178 cr = encoder.flush(dst);
1179 if (!cr.isUnderflow()) {
1180 cr.throwException();
1181 }
1182 } catch (CharacterCodingException x) {
1183 throw new IllegalStateException(x);
1184 }
1185 dst.flip();
1186 return dst;
1187 }
1188
1189 static String decodeString(ByteBuffer src, Charset charset) {
1190 final CharsetDecoder decoder = CharsetUtil.getDecoder(charset);
1191 final CharBuffer dst = CharBuffer.allocate(
1192 (int) ((double) src.remaining() * decoder.maxCharsPerByte()));
1193 try {
1194 CoderResult cr = decoder.decode(src, dst, true);
1195 if (!cr.isUnderflow()) {
1196 cr.throwException();
1197 }
1198 cr = decoder.flush(dst);
1199 if (!cr.isUnderflow()) {
1200 cr.throwException();
1201 }
1202 } catch (CharacterCodingException x) {
1203 throw new IllegalStateException(x);
1204 }
1205 return dst.flip().toString();
1206 }
1207
1208 private ChannelBuffers() {
1209
1210 }
1211 }