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 EmptyChannelBuffer();
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 public static ChannelBuffer wrappedBuffer(ByteBuffer... buffers) {
460 return wrappedBuffer(false, buffers);
461 }
462
463
464
465
466
467
468
469
470
471
472
473
474 public static ChannelBuffer wrappedBuffer(boolean gathering, ByteBuffer... buffers) {
475 switch (buffers.length) {
476 case 0:
477 break;
478 case 1:
479 if (buffers[0].hasRemaining()) {
480 return wrappedBuffer(buffers[0]);
481 }
482 break;
483 default:
484 ByteOrder order = null;
485 final List<ChannelBuffer> components = new ArrayList<ChannelBuffer>(buffers.length);
486 for (ByteBuffer b: buffers) {
487 if (b == null) {
488 break;
489 }
490 if (b.hasRemaining()) {
491 if (order != null) {
492 if (!order.equals(b.order())) {
493 throw new IllegalArgumentException(
494 "inconsistent byte order");
495 }
496 } else {
497 order = b.order();
498 }
499 components.add(wrappedBuffer(b));
500 }
501 }
502 return compositeBuffer(order, components, gathering);
503 }
504
505 return EMPTY_BUFFER;
506 }
507
508
509
510
511
512
513 public static ChannelBuffer copiedBuffer(byte[] array) {
514 return copiedBuffer(BIG_ENDIAN, array);
515 }
516
517
518
519
520
521
522
523 public static ChannelBuffer copiedBuffer(ByteOrder endianness, byte[] array) {
524 if (endianness == BIG_ENDIAN) {
525 if (array.length == 0) {
526 return EMPTY_BUFFER;
527 }
528 return new BigEndianHeapChannelBuffer(array.clone());
529 } else if (endianness == LITTLE_ENDIAN) {
530 if (array.length == 0) {
531 return EMPTY_BUFFER;
532 }
533 return new LittleEndianHeapChannelBuffer(array.clone());
534 } else {
535 throw new NullPointerException("endianness");
536 }
537 }
538
539
540
541
542
543
544
545 public static ChannelBuffer copiedBuffer(byte[] array, int offset, int length) {
546 return copiedBuffer(BIG_ENDIAN, array, offset, length);
547 }
548
549
550
551
552
553
554
555 public static ChannelBuffer copiedBuffer(ByteOrder endianness, byte[] array, int offset, int length) {
556 if (endianness == null) {
557 throw new NullPointerException("endianness");
558 }
559 if (length == 0) {
560 return EMPTY_BUFFER;
561 }
562 byte[] copy = new byte[length];
563 System.arraycopy(array, offset, copy, 0, length);
564 return wrappedBuffer(endianness, copy);
565 }
566
567
568
569
570
571
572
573 public static ChannelBuffer copiedBuffer(ByteBuffer buffer) {
574 int length = buffer.remaining();
575 if (length == 0) {
576 return EMPTY_BUFFER;
577 }
578 byte[] copy = new byte[length];
579 int position = buffer.position();
580 try {
581 buffer.get(copy);
582 } finally {
583 buffer.position(position);
584 }
585 return wrappedBuffer(buffer.order(), copy);
586 }
587
588
589
590
591
592
593
594 public static ChannelBuffer copiedBuffer(ChannelBuffer buffer) {
595 if (buffer.readable()) {
596 return buffer.copy();
597 } else {
598 return EMPTY_BUFFER;
599 }
600 }
601
602
603
604
605
606
607
608 public static ChannelBuffer copiedBuffer(byte[]... arrays) {
609 return copiedBuffer(BIG_ENDIAN, arrays);
610 }
611
612
613
614
615
616
617
618 public static ChannelBuffer copiedBuffer(ByteOrder endianness, byte[]... arrays) {
619 switch (arrays.length) {
620 case 0:
621 return EMPTY_BUFFER;
622 case 1:
623 if (arrays[0].length == 0) {
624 return EMPTY_BUFFER;
625 } else {
626 return copiedBuffer(endianness, arrays[0]);
627 }
628 }
629
630
631 int length = 0;
632 for (byte[] a: arrays) {
633 if (Integer.MAX_VALUE - length < a.length) {
634 throw new IllegalArgumentException(
635 "The total length of the specified arrays is too big.");
636 }
637 length += a.length;
638 }
639
640 if (length == 0) {
641 return EMPTY_BUFFER;
642 }
643
644 byte[] mergedArray = new byte[length];
645 for (int i = 0, j = 0; i < arrays.length; i ++) {
646 byte[] a = arrays[i];
647 System.arraycopy(a, 0, mergedArray, j, a.length);
648 j += a.length;
649 }
650
651 return wrappedBuffer(endianness, mergedArray);
652 }
653
654
655
656
657
658
659
660
661
662
663
664 public static ChannelBuffer copiedBuffer(ChannelBuffer... buffers) {
665 switch (buffers.length) {
666 case 0:
667 return EMPTY_BUFFER;
668 case 1:
669 return copiedBuffer(buffers[0]);
670 }
671
672 ChannelBuffer[] copiedBuffers = new ChannelBuffer[buffers.length];
673 for (int i = 0; i < buffers.length; i ++) {
674 copiedBuffers[i] = copiedBuffer(buffers[i]);
675 }
676 return wrappedBuffer(false, copiedBuffers);
677 }
678
679
680
681
682
683
684
685
686
687
688
689 public static ChannelBuffer copiedBuffer(ByteBuffer... buffers) {
690 switch (buffers.length) {
691 case 0:
692 return EMPTY_BUFFER;
693 case 1:
694 return copiedBuffer(buffers[0]);
695 }
696
697 ChannelBuffer[] copiedBuffers = new ChannelBuffer[buffers.length];
698 for (int i = 0; i < buffers.length; i ++) {
699 copiedBuffers[i] = copiedBuffer(buffers[i]);
700 }
701 return wrappedBuffer(false, copiedBuffers);
702 }
703
704
705
706
707
708
709
710 public static ChannelBuffer copiedBuffer(CharSequence string, Charset charset) {
711 return copiedBuffer(BIG_ENDIAN, string, charset);
712 }
713
714
715
716
717
718
719
720 public static ChannelBuffer copiedBuffer(
721 CharSequence string, int offset, int length, Charset charset) {
722 return copiedBuffer(BIG_ENDIAN, string, offset, length, charset);
723 }
724
725
726
727
728
729
730
731
732 public static ChannelBuffer copiedBuffer(ByteOrder endianness, CharSequence string, Charset charset) {
733 if (string == null) {
734 throw new NullPointerException("string");
735 }
736
737 if (string instanceof CharBuffer) {
738 return copiedBuffer(endianness, (CharBuffer) string, charset);
739 }
740
741 return copiedBuffer(endianness, CharBuffer.wrap(string), charset);
742 }
743
744
745
746
747
748
749
750
751 public static ChannelBuffer copiedBuffer(
752 ByteOrder endianness, CharSequence string, int offset, int length, Charset charset) {
753 if (string == null) {
754 throw new NullPointerException("string");
755 }
756 if (length == 0) {
757 return EMPTY_BUFFER;
758 }
759
760 if (string instanceof CharBuffer) {
761 CharBuffer buf = (CharBuffer) string;
762 if (buf.hasArray()) {
763 return copiedBuffer(
764 endianness,
765 buf.array(),
766 buf.arrayOffset() + buf.position() + offset,
767 length, charset);
768 }
769
770 buf = buf.slice();
771 buf.limit(length);
772 buf.position(offset);
773 return copiedBuffer(endianness, buf, charset);
774 }
775
776 return copiedBuffer(
777 endianness, CharBuffer.wrap(string, offset, offset + length),
778 charset);
779 }
780
781
782
783
784
785
786
787 public static ChannelBuffer copiedBuffer(char[] array, Charset charset) {
788 return copiedBuffer(BIG_ENDIAN, array, 0, array.length, charset);
789 }
790
791
792
793
794
795
796
797 public static ChannelBuffer copiedBuffer(
798 char[] array, int offset, int length, Charset charset) {
799 return copiedBuffer(BIG_ENDIAN, array, offset, length, charset);
800 }
801
802
803
804
805
806
807
808
809 public static ChannelBuffer copiedBuffer(ByteOrder endianness, char[] array, Charset charset) {
810 return copiedBuffer(endianness, array, 0, array.length, charset);
811 }
812
813
814
815
816
817
818
819
820 public static ChannelBuffer copiedBuffer(
821 ByteOrder endianness, char[] array, int offset, int length, Charset charset) {
822 if (array == null) {
823 throw new NullPointerException("array");
824 }
825 if (length == 0) {
826 return EMPTY_BUFFER;
827 }
828 return copiedBuffer(
829 endianness, CharBuffer.wrap(array, offset, length), charset);
830 }
831
832 private static ChannelBuffer copiedBuffer(ByteOrder endianness, CharBuffer buffer, Charset charset) {
833 CharBuffer src = buffer;
834 ByteBuffer dst = encodeString(src, charset);
835 ChannelBuffer result = wrappedBuffer(endianness, dst.array());
836 result.writerIndex(dst.remaining());
837 return result;
838 }
839
840
841
842
843
844
845
846 public static ChannelBuffer unmodifiableBuffer(ChannelBuffer buffer) {
847 if (buffer instanceof ReadOnlyChannelBuffer) {
848 buffer = ((ReadOnlyChannelBuffer) buffer).unwrap();
849 }
850 return new ReadOnlyChannelBuffer(buffer);
851 }
852
853
854
855
856 public static ChannelBuffer hexDump(String hexString) {
857 int len = hexString.length();
858 byte[] hexData = new byte[len / 2];
859 for (int i = 0; i < len; i += 2) {
860 hexData[i / 2] = (byte) ((Character.digit(hexString.charAt(i), 16) << 4)
861 + Character.digit(hexString.charAt(i + 1), 16));
862 }
863 return wrappedBuffer(hexData);
864 }
865
866
867
868
869
870 public static String hexDump(ChannelBuffer buffer) {
871 return hexDump(buffer, buffer.readerIndex(), buffer.readableBytes());
872 }
873
874
875
876
877
878 public static String hexDump(ChannelBuffer buffer, int fromIndex, int length) {
879 if (length < 0) {
880 throw new IllegalArgumentException("length: " + length);
881 }
882 if (length == 0) {
883 return "";
884 }
885
886 int endIndex = fromIndex + length;
887 char[] buf = new char[length << 1];
888
889 int srcIdx = fromIndex;
890 int dstIdx = 0;
891 for (; srcIdx < endIndex; srcIdx ++, dstIdx += 2) {
892 System.arraycopy(
893 HEXDUMP_TABLE, buffer.getUnsignedByte(srcIdx) << 1,
894 buf, dstIdx, 2);
895 }
896
897 return new String(buf);
898 }
899
900
901
902
903
904 public static int hashCode(ChannelBuffer buffer) {
905 final int aLen = buffer.readableBytes();
906 final int intCount = aLen >>> 2;
907 final int byteCount = aLen & 3;
908
909 int hashCode = 1;
910 int arrayIndex = buffer.readerIndex();
911 if (buffer.order() == BIG_ENDIAN) {
912 for (int i = intCount; i > 0; i --) {
913 hashCode = 31 * hashCode + buffer.getInt(arrayIndex);
914 arrayIndex += 4;
915 }
916 } else {
917 for (int i = intCount; i > 0; i --) {
918 hashCode = 31 * hashCode + swapInt(buffer.getInt(arrayIndex));
919 arrayIndex += 4;
920 }
921 }
922
923 for (int i = byteCount; i > 0; i --) {
924 hashCode = 31 * hashCode + buffer.getByte(arrayIndex ++);
925 }
926
927 if (hashCode == 0) {
928 hashCode = 1;
929 }
930
931 return hashCode;
932 }
933
934
935
936
937
938
939 public static boolean equals(ChannelBuffer bufferA, ChannelBuffer bufferB) {
940 final int aLen = bufferA.readableBytes();
941 if (aLen != bufferB.readableBytes()) {
942 return false;
943 }
944
945 final int longCount = aLen >>> 3;
946 final int byteCount = aLen & 7;
947
948 int aIndex = bufferA.readerIndex();
949 int bIndex = bufferB.readerIndex();
950
951 if (bufferA.order() == bufferB.order()) {
952 for (int i = longCount; i > 0; i --) {
953 if (bufferA.getLong(aIndex) != bufferB.getLong(bIndex)) {
954 return false;
955 }
956 aIndex += 8;
957 bIndex += 8;
958 }
959 } else {
960 for (int i = longCount; i > 0; i --) {
961 if (bufferA.getLong(aIndex) != swapLong(bufferB.getLong(bIndex))) {
962 return false;
963 }
964 aIndex += 8;
965 bIndex += 8;
966 }
967 }
968
969 for (int i = byteCount; i > 0; i --) {
970 if (bufferA.getByte(aIndex) != bufferB.getByte(bIndex)) {
971 return false;
972 }
973 aIndex ++;
974 bIndex ++;
975 }
976
977 return true;
978 }
979
980
981
982
983
984 public static int compare(ChannelBuffer bufferA, ChannelBuffer bufferB) {
985 final int aLen = bufferA.readableBytes();
986 final int bLen = bufferB.readableBytes();
987 final int minLength = Math.min(aLen, bLen);
988 final int uintCount = minLength >>> 2;
989 final int byteCount = minLength & 3;
990
991 int aIndex = bufferA.readerIndex();
992 int bIndex = bufferB.readerIndex();
993
994 if (bufferA.order() == bufferB.order()) {
995 for (int i = uintCount; i > 0; i --) {
996 long va = bufferA.getUnsignedInt(aIndex);
997 long vb = bufferB.getUnsignedInt(bIndex);
998 if (va > vb) {
999 return 1;
1000 }
1001 if (va < vb) {
1002 return -1;
1003 }
1004 aIndex += 4;
1005 bIndex += 4;
1006 }
1007 } else {
1008 for (int i = uintCount; i > 0; i --) {
1009 long va = bufferA.getUnsignedInt(aIndex);
1010 long vb = swapInt(bufferB.getInt(bIndex)) & 0xFFFFFFFFL;
1011 if (va > vb) {
1012 return 1;
1013 }
1014 if (va < vb) {
1015 return -1;
1016 }
1017 aIndex += 4;
1018 bIndex += 4;
1019 }
1020 }
1021
1022 for (int i = byteCount; i > 0; i --) {
1023 short va = bufferA.getUnsignedByte(aIndex);
1024 short vb = bufferB.getUnsignedByte(bIndex);
1025 if (va > vb) {
1026 return 1;
1027 }
1028 if (va < vb) {
1029 return -1;
1030 }
1031 aIndex ++;
1032 bIndex ++;
1033 }
1034
1035 return aLen - bLen;
1036 }
1037
1038
1039
1040
1041
1042 public static int indexOf(ChannelBuffer buffer, int fromIndex, int toIndex, byte value) {
1043 if (fromIndex <= toIndex) {
1044 return firstIndexOf(buffer, fromIndex, toIndex, value);
1045 } else {
1046 return lastIndexOf(buffer, fromIndex, toIndex, value);
1047 }
1048 }
1049
1050
1051
1052
1053
1054 public static int indexOf(
1055 ChannelBuffer buffer, int fromIndex, int toIndex, ChannelBufferIndexFinder indexFinder) {
1056 if (fromIndex <= toIndex) {
1057 return firstIndexOf(buffer, fromIndex, toIndex, indexFinder);
1058 } else {
1059 return lastIndexOf(buffer, fromIndex, toIndex, indexFinder);
1060 }
1061 }
1062
1063
1064
1065
1066 public static short swapShort(short value) {
1067 return (short) (value << 8 | value >>> 8 & 0xff);
1068 }
1069
1070
1071
1072
1073 public static int swapMedium(int value) {
1074 return value << 16 & 0xff0000 | value & 0xff00 | value >>> 16 & 0xff;
1075 }
1076
1077
1078
1079
1080 public static int swapInt(int value) {
1081 return swapShort((short) value) << 16 |
1082 swapShort((short) (value >>> 16)) & 0xffff;
1083 }
1084
1085
1086
1087
1088 public static long swapLong(long value) {
1089 return (long) swapInt((int) value) << 32 |
1090 swapInt((int) (value >>> 32)) & 0xffffffffL;
1091 }
1092
1093 private static int firstIndexOf(ChannelBuffer buffer, int fromIndex, int toIndex, byte value) {
1094 fromIndex = Math.max(fromIndex, 0);
1095 if (fromIndex >= toIndex || buffer.capacity() == 0) {
1096 return -1;
1097 }
1098
1099 for (int i = fromIndex; i < toIndex; i ++) {
1100 if (buffer.getByte(i) == value) {
1101 return i;
1102 }
1103 }
1104
1105 return -1;
1106 }
1107
1108 private static int lastIndexOf(ChannelBuffer buffer, int fromIndex, int toIndex, byte value) {
1109 fromIndex = Math.min(fromIndex, buffer.capacity());
1110 if (fromIndex < 0 || buffer.capacity() == 0) {
1111 return -1;
1112 }
1113
1114 for (int i = fromIndex - 1; i >= toIndex; i --) {
1115 if (buffer.getByte(i) == value) {
1116 return i;
1117 }
1118 }
1119
1120 return -1;
1121 }
1122
1123 private static int firstIndexOf(
1124 ChannelBuffer buffer, int fromIndex, int toIndex, ChannelBufferIndexFinder indexFinder) {
1125 fromIndex = Math.max(fromIndex, 0);
1126 if (fromIndex >= toIndex || buffer.capacity() == 0) {
1127 return -1;
1128 }
1129
1130 for (int i = fromIndex; i < toIndex; i ++) {
1131 if (indexFinder.find(buffer, i)) {
1132 return i;
1133 }
1134 }
1135
1136 return -1;
1137 }
1138
1139 private static int lastIndexOf(
1140 ChannelBuffer buffer, int fromIndex, int toIndex, ChannelBufferIndexFinder indexFinder) {
1141 fromIndex = Math.min(fromIndex, buffer.capacity());
1142 if (fromIndex < 0 || buffer.capacity() == 0) {
1143 return -1;
1144 }
1145
1146 for (int i = fromIndex - 1; i >= toIndex; i --) {
1147 if (indexFinder.find(buffer, i)) {
1148 return i;
1149 }
1150 }
1151
1152 return -1;
1153 }
1154
1155 static ByteBuffer encodeString(CharBuffer src, Charset charset) {
1156 final CharsetEncoder encoder = CharsetUtil.getEncoder(charset);
1157 final ByteBuffer dst = ByteBuffer.allocate(
1158 (int) ((double) src.remaining() * encoder.maxBytesPerChar()));
1159 try {
1160 CoderResult cr = encoder.encode(src, dst, true);
1161 if (!cr.isUnderflow()) {
1162 cr.throwException();
1163 }
1164 cr = encoder.flush(dst);
1165 if (!cr.isUnderflow()) {
1166 cr.throwException();
1167 }
1168 } catch (CharacterCodingException x) {
1169 throw new IllegalStateException(x);
1170 }
1171 dst.flip();
1172 return dst;
1173 }
1174
1175 static String decodeString(ByteBuffer src, Charset charset) {
1176 final CharsetDecoder decoder = CharsetUtil.getDecoder(charset);
1177 final CharBuffer dst = CharBuffer.allocate(
1178 (int) ((double) src.remaining() * decoder.maxCharsPerByte()));
1179 try {
1180 CoderResult cr = decoder.decode(src, dst, true);
1181 if (!cr.isUnderflow()) {
1182 cr.throwException();
1183 }
1184 cr = decoder.flush(dst);
1185 if (!cr.isUnderflow()) {
1186 cr.throwException();
1187 }
1188 } catch (CharacterCodingException x) {
1189 throw new IllegalStateException(x);
1190 }
1191 return dst.flip().toString();
1192 }
1193
1194 private ChannelBuffers() {
1195
1196 }
1197 }