1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 package org.eclipse.jetty.util;
20
21 import java.io.File;
22 import java.io.IOException;
23 import java.io.InputStream;
24 import java.io.OutputStream;
25 import java.io.RandomAccessFile;
26 import java.nio.BufferOverflowException;
27 import java.nio.ByteBuffer;
28 import java.nio.channels.FileChannel;
29 import java.nio.channels.FileChannel.MapMode;
30 import java.nio.charset.Charset;
31 import java.nio.charset.StandardCharsets;
32 import java.util.Arrays;
33
34 import org.eclipse.jetty.util.resource.Resource;
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 class BufferUtil
89 {
90 static final int TEMP_BUFFER_SIZE = 4096;
91 static final byte SPACE = 0x20;
92 static final byte MINUS = '-';
93 static final byte[] DIGIT =
94 {(byte)'0', (byte)'1', (byte)'2', (byte)'3', (byte)'4', (byte)'5', (byte)'6', (byte)'7', (byte)'8', (byte)'9', (byte)'A', (byte)'B', (byte)'C', (byte)'D',
95 (byte)'E', (byte)'F'};
96
97 public static final ByteBuffer EMPTY_BUFFER = ByteBuffer.wrap(new byte[0]);
98
99
100
101
102
103
104
105
106 public static ByteBuffer allocate(int capacity)
107 {
108 ByteBuffer buf = ByteBuffer.allocate(capacity);
109 buf.limit(0);
110 return buf;
111 }
112
113
114
115
116
117
118
119
120 public static ByteBuffer allocateDirect(int capacity)
121 {
122 ByteBuffer buf = ByteBuffer.allocateDirect(capacity);
123 buf.limit(0);
124 return buf;
125 }
126
127
128
129
130
131
132
133 public static void clear(ByteBuffer buffer)
134 {
135 if (buffer != null)
136 {
137 buffer.position(0);
138 buffer.limit(0);
139 }
140 }
141
142
143
144
145
146
147 public static void clearToFill(ByteBuffer buffer)
148 {
149 if (buffer != null)
150 {
151 buffer.position(0);
152 buffer.limit(buffer.capacity());
153 }
154 }
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170 public static int flipToFill(ByteBuffer buffer)
171 {
172 int position = buffer.position();
173 int limit = buffer.limit();
174 if (position == limit)
175 {
176 buffer.position(0);
177 buffer.limit(buffer.capacity());
178 return 0;
179 }
180
181 int capacity = buffer.capacity();
182 if (limit == capacity)
183 {
184 buffer.compact();
185 return 0;
186 }
187
188 buffer.position(limit);
189 buffer.limit(capacity);
190 return position;
191 }
192
193
194
195
196
197
198
199
200
201
202
203
204 public static void flipToFlush(ByteBuffer buffer, int position)
205 {
206 buffer.limit(buffer.position());
207 buffer.position(position);
208 }
209
210
211
212
213
214
215
216 public static byte[] toArray(ByteBuffer buffer)
217 {
218 if (buffer.hasArray())
219 {
220 byte[] array = buffer.array();
221 int from=buffer.arrayOffset() + buffer.position();
222 return Arrays.copyOfRange(array,from,from+buffer.remaining());
223 }
224 else
225 {
226 byte[] to = new byte[buffer.remaining()];
227 buffer.slice().get(to);
228 return to;
229 }
230 }
231
232
233
234
235
236
237 public static boolean isEmpty(ByteBuffer buf)
238 {
239 return buf == null || buf.remaining() == 0;
240 }
241
242
243
244
245
246
247 public static boolean hasContent(ByteBuffer buf)
248 {
249 return buf != null && buf.remaining() > 0;
250 }
251
252
253
254
255
256
257 public static boolean isFull(ByteBuffer buf)
258 {
259 return buf != null && buf.limit() == buf.capacity();
260 }
261
262
263
264
265
266
267 public static int length(ByteBuffer buffer)
268 {
269 return buffer == null ? 0 : buffer.remaining();
270 }
271
272
273
274
275
276
277 public static int space(ByteBuffer buffer)
278 {
279 if (buffer == null)
280 return 0;
281 return buffer.capacity() - buffer.limit();
282 }
283
284
285
286
287
288
289 public static boolean compact(ByteBuffer buffer)
290 {
291 if (buffer.position()==0)
292 return false;
293 boolean full = buffer.limit() == buffer.capacity();
294 buffer.compact().flip();
295 return full && buffer.limit() < buffer.capacity();
296 }
297
298
299
300
301
302
303
304
305 public static int put(ByteBuffer from, ByteBuffer to)
306 {
307 int put;
308 int remaining = from.remaining();
309 if (remaining > 0)
310 {
311 if (remaining <= to.remaining())
312 {
313 to.put(from);
314 put = remaining;
315 from.position(0);
316 from.limit(0);
317 }
318 else if (from.hasArray())
319 {
320 put = to.remaining();
321 to.put(from.array(), from.arrayOffset() + from.position(), put);
322 from.position(from.position() + put);
323 }
324 else
325 {
326 put = to.remaining();
327 ByteBuffer slice = from.slice();
328 slice.limit(put);
329 to.put(slice);
330 from.position(from.position() + put);
331 }
332 }
333 else
334 put = 0;
335
336 return put;
337 }
338
339
340
341
342
343
344
345
346
347 public static int flipPutFlip(ByteBuffer from, ByteBuffer to)
348 {
349 return append(to,from);
350 }
351
352
353
354
355
356
357
358
359
360 public static void append(ByteBuffer to, byte[] b, int off, int len) throws BufferOverflowException
361 {
362 int pos = flipToFill(to);
363 try
364 {
365 to.put(b, off, len);
366 }
367 finally
368 {
369 flipToFlush(to, pos);
370 }
371 }
372
373
374
375
376
377
378 public static void append(ByteBuffer to, byte b)
379 {
380 int pos = flipToFill(to);
381 try
382 {
383 to.put(b);
384 }
385 finally
386 {
387 flipToFlush(to, pos);
388 }
389 }
390
391
392
393
394
395
396 public static int append(ByteBuffer to, ByteBuffer b)
397 {
398 int pos = flipToFill(to);
399 try
400 {
401 return put(b, to);
402 }
403 finally
404 {
405 flipToFlush(to, pos);
406 }
407 }
408
409
410
411
412
413
414
415
416
417 public static int fill(ByteBuffer to, byte[] b, int off, int len)
418 {
419 int pos = flipToFill(to);
420 try
421 {
422 int remaining = to.remaining();
423 int take = remaining < len ? remaining : len;
424 to.put(b, off, take);
425 return take;
426 }
427 finally
428 {
429 flipToFlush(to, pos);
430 }
431 }
432
433
434
435 public static void readFrom(File file, ByteBuffer buffer) throws IOException
436 {
437 try(RandomAccessFile raf = new RandomAccessFile(file,"r"))
438 {
439 FileChannel channel = raf.getChannel();
440 long needed=raf.length();
441
442 while (needed>0 && buffer.hasRemaining())
443 needed=needed-channel.read(buffer);
444 }
445 }
446
447
448 public static void readFrom(InputStream is, int needed, ByteBuffer buffer) throws IOException
449 {
450 ByteBuffer tmp = allocate(8192);
451
452 while (needed > 0 && buffer.hasRemaining())
453 {
454 int l = is.read(tmp.array(), 0, 8192);
455 if (l < 0)
456 break;
457 tmp.position(0);
458 tmp.limit(l);
459 buffer.put(tmp);
460 }
461 }
462
463
464 public static void writeTo(ByteBuffer buffer, OutputStream out) throws IOException
465 {
466 if (buffer.hasArray())
467 {
468 out.write(buffer.array(),buffer.arrayOffset() + buffer.position(),buffer.remaining());
469
470 buffer.position(buffer.position() + buffer.remaining());
471 }
472 else
473 {
474 byte[] bytes = new byte[TEMP_BUFFER_SIZE];
475 while(buffer.hasRemaining()){
476 int byteCountToWrite = Math.min(buffer.remaining(), TEMP_BUFFER_SIZE);
477 buffer.get(bytes, 0, byteCountToWrite);
478 out.write(bytes,0 , byteCountToWrite);
479 }
480 }
481 }
482
483
484
485
486
487
488 public static String toString(ByteBuffer buffer)
489 {
490 return toString(buffer, StandardCharsets.ISO_8859_1);
491 }
492
493
494
495
496
497
498 public static String toUTF8String(ByteBuffer buffer)
499 {
500 return toString(buffer, StandardCharsets.UTF_8);
501 }
502
503
504
505
506
507
508
509 public static String toString(ByteBuffer buffer, Charset charset)
510 {
511 if (buffer == null)
512 return null;
513 byte[] array = buffer.hasArray() ? buffer.array() : null;
514 if (array == null)
515 {
516 byte[] to = new byte[buffer.remaining()];
517 buffer.slice().get(to);
518 return new String(to, 0, to.length, charset);
519 }
520 return new String(array, buffer.arrayOffset() + buffer.position(), buffer.remaining(), charset);
521 }
522
523
524
525
526
527
528
529 public static String toString(ByteBuffer buffer, int position, int length, Charset charset)
530 {
531 if (buffer == null)
532 return null;
533 byte[] array = buffer.hasArray() ? buffer.array() : null;
534 if (array == null)
535 {
536 ByteBuffer ro = buffer.asReadOnlyBuffer();
537 ro.position(position);
538 ro.limit(position + length);
539 byte[] to = new byte[length];
540 ro.get(to);
541 return new String(to, 0, to.length, charset);
542 }
543 return new String(array, buffer.arrayOffset() + position, length, charset);
544 }
545
546
547
548
549
550
551
552
553
554 public static int toInt(ByteBuffer buffer)
555 {
556 int val = 0;
557 boolean started = false;
558 boolean minus = false;
559
560 for (int i = buffer.position(); i < buffer.limit(); i++)
561 {
562 byte b = buffer.get(i);
563 if (b <= SPACE)
564 {
565 if (started)
566 break;
567 }
568 else if (b >= '0' && b <= '9')
569 {
570 val = val * 10 + (b - '0');
571 started = true;
572 }
573 else if (b == MINUS && !started)
574 {
575 minus = true;
576 }
577 else
578 break;
579 }
580
581 if (started)
582 return minus ? (-val) : val;
583 throw new NumberFormatException(toString(buffer));
584 }
585
586
587
588
589
590
591
592
593
594 public static int takeInt(ByteBuffer buffer)
595 {
596 int val = 0;
597 boolean started = false;
598 boolean minus = false;
599 int i;
600 for (i = buffer.position(); i < buffer.limit(); i++)
601 {
602 byte b = buffer.get(i);
603 if (b <= SPACE)
604 {
605 if (started)
606 break;
607 }
608 else if (b >= '0' && b <= '9')
609 {
610 val = val * 10 + (b - '0');
611 started = true;
612 }
613 else if (b == MINUS && !started)
614 {
615 minus = true;
616 }
617 else
618 break;
619 }
620
621 if (started)
622 {
623 buffer.position(i);
624 return minus ? (-val) : val;
625 }
626 throw new NumberFormatException(toString(buffer));
627 }
628
629
630
631
632
633
634
635
636 public static long toLong(ByteBuffer buffer)
637 {
638 long val = 0;
639 boolean started = false;
640 boolean minus = false;
641
642 for (int i = buffer.position(); i < buffer.limit(); i++)
643 {
644 byte b = buffer.get(i);
645 if (b <= SPACE)
646 {
647 if (started)
648 break;
649 }
650 else if (b >= '0' && b <= '9')
651 {
652 val = val * 10L + (b - '0');
653 started = true;
654 }
655 else if (b == MINUS && !started)
656 {
657 minus = true;
658 }
659 else
660 break;
661 }
662
663 if (started)
664 return minus ? (-val) : val;
665 throw new NumberFormatException(toString(buffer));
666 }
667
668 public static void putHexInt(ByteBuffer buffer, int n)
669 {
670 if (n < 0)
671 {
672 buffer.put((byte)'-');
673
674 if (n == Integer.MIN_VALUE)
675 {
676 buffer.put((byte)(0x7f & '8'));
677 buffer.put((byte)(0x7f & '0'));
678 buffer.put((byte)(0x7f & '0'));
679 buffer.put((byte)(0x7f & '0'));
680 buffer.put((byte)(0x7f & '0'));
681 buffer.put((byte)(0x7f & '0'));
682 buffer.put((byte)(0x7f & '0'));
683 buffer.put((byte)(0x7f & '0'));
684
685 return;
686 }
687 n = -n;
688 }
689
690 if (n < 0x10)
691 {
692 buffer.put(DIGIT[n]);
693 }
694 else
695 {
696 boolean started = false;
697
698 for (int hexDivisor : hexDivisors)
699 {
700 if (n < hexDivisor)
701 {
702 if (started)
703 buffer.put((byte)'0');
704 continue;
705 }
706
707 started = true;
708 int d = n / hexDivisor;
709 buffer.put(DIGIT[d]);
710 n = n - d * hexDivisor;
711 }
712 }
713 }
714
715
716 public static void putDecInt(ByteBuffer buffer, int n)
717 {
718 if (n < 0)
719 {
720 buffer.put((byte)'-');
721
722 if (n == Integer.MIN_VALUE)
723 {
724 buffer.put((byte)'2');
725 n = 147483648;
726 }
727 else
728 n = -n;
729 }
730
731 if (n < 10)
732 {
733 buffer.put(DIGIT[n]);
734 }
735 else
736 {
737 boolean started = false;
738
739 for (int decDivisor : decDivisors)
740 {
741 if (n < decDivisor)
742 {
743 if (started)
744 buffer.put((byte)'0');
745 continue;
746 }
747
748 started = true;
749 int d = n / decDivisor;
750 buffer.put(DIGIT[d]);
751 n = n - d * decDivisor;
752 }
753 }
754 }
755
756 public static void putDecLong(ByteBuffer buffer, long n)
757 {
758 if (n < 0)
759 {
760 buffer.put((byte)'-');
761
762 if (n == Long.MIN_VALUE)
763 {
764 buffer.put((byte)'9');
765 n = 223372036854775808L;
766 }
767 else
768 n = -n;
769 }
770
771 if (n < 10)
772 {
773 buffer.put(DIGIT[(int)n]);
774 }
775 else
776 {
777 boolean started = false;
778
779 for (long aDecDivisorsL : decDivisorsL)
780 {
781 if (n < aDecDivisorsL)
782 {
783 if (started)
784 buffer.put((byte)'0');
785 continue;
786 }
787
788 started = true;
789 long d = n / aDecDivisorsL;
790 buffer.put(DIGIT[(int)d]);
791 n = n - d * aDecDivisorsL;
792 }
793 }
794 }
795
796 public static ByteBuffer toBuffer(int value)
797 {
798 ByteBuffer buf = ByteBuffer.allocate(32);
799 putDecInt(buf, value);
800 return buf;
801 }
802
803 public static ByteBuffer toBuffer(long value)
804 {
805 ByteBuffer buf = ByteBuffer.allocate(32);
806 putDecLong(buf, value);
807 return buf;
808 }
809
810 public static ByteBuffer toBuffer(String s)
811 {
812 return ByteBuffer.wrap(s.getBytes(StandardCharsets.ISO_8859_1));
813 }
814
815 public static ByteBuffer toDirectBuffer(String s)
816 {
817 byte[] bytes = s.getBytes(StandardCharsets.ISO_8859_1);
818 ByteBuffer buf = ByteBuffer.allocateDirect(bytes.length);
819 buf.put(bytes);
820 buf.flip();
821 return buf;
822 }
823
824 public static ByteBuffer toBuffer(String s, Charset charset)
825 {
826 return ByteBuffer.wrap(s.getBytes(charset));
827 }
828
829 public static ByteBuffer toDirectBuffer(String s, Charset charset)
830 {
831 byte[] bytes = s.getBytes(charset);
832 ByteBuffer buf = ByteBuffer.allocateDirect(bytes.length);
833 buf.put(bytes);
834 buf.flip();
835 return buf;
836 }
837
838
839
840
841
842
843
844
845 public static ByteBuffer toBuffer(byte array[])
846 {
847 return ByteBuffer.wrap(array);
848 }
849
850
851
852
853
854
855
856
857
858
859
860
861 public static ByteBuffer toBuffer(byte array[], int offset, int length)
862 {
863 return ByteBuffer.wrap(array, offset, length);
864 }
865
866 public static ByteBuffer toMappedBuffer(File file) throws IOException
867 {
868 try (RandomAccessFile raf = new RandomAccessFile(file, "r"))
869 {
870 return raf.getChannel().map(MapMode.READ_ONLY, 0, raf.length());
871 }
872 }
873
874 public static ByteBuffer toBuffer(Resource resource,boolean direct) throws IOException
875 {
876 int len=(int)resource.length();
877 if (len<0)
878 throw new IllegalArgumentException("invalid resource: "+String.valueOf(resource)+" len="+len);
879
880 ByteBuffer buffer = direct?BufferUtil.allocateDirect(len):BufferUtil.allocate(len);
881
882 int pos=BufferUtil.flipToFill(buffer);
883 if (resource.getFile()!=null)
884 BufferUtil.readFrom(resource.getFile(),buffer);
885 else
886 {
887 try (InputStream is = resource.getInputStream();)
888 {
889 BufferUtil.readFrom(is,len,buffer);
890 }
891 }
892 BufferUtil.flipToFlush(buffer,pos);
893
894 return buffer;
895 }
896
897 public static String toSummaryString(ByteBuffer buffer)
898 {
899 if (buffer == null)
900 return "null";
901 StringBuilder buf = new StringBuilder();
902 buf.append("[p=");
903 buf.append(buffer.position());
904 buf.append(",l=");
905 buf.append(buffer.limit());
906 buf.append(",c=");
907 buf.append(buffer.capacity());
908 buf.append(",r=");
909 buf.append(buffer.remaining());
910 buf.append("]");
911 return buf.toString();
912 }
913
914 public static String toDetailString(ByteBuffer[] buffer)
915 {
916 StringBuilder builder = new StringBuilder();
917 builder.append('[');
918 for (int i = 0; i < buffer.length; i++)
919 {
920 if (i > 0) builder.append(',');
921 builder.append(toDetailString(buffer[i]));
922 }
923 builder.append(']');
924 return builder.toString();
925 }
926
927
928
929
930
931
932
933
934 private static void idString(ByteBuffer buffer, StringBuilder out)
935 {
936 out.append(buffer.getClass().getSimpleName());
937 out.append("@");
938 if (buffer.hasArray() && buffer.arrayOffset()==4)
939 {
940 out.append('T');
941 byte[] array = buffer.array();
942 TypeUtil.toHex(array[0],out);
943 TypeUtil.toHex(array[1],out);
944 TypeUtil.toHex(array[2],out);
945 TypeUtil.toHex(array[3],out);
946 }
947 else
948 out.append(Integer.toHexString(System.identityHashCode(buffer)));
949 }
950
951
952
953
954
955
956 public static String toIDString(ByteBuffer buffer)
957 {
958 StringBuilder buf = new StringBuilder();
959 idString(buffer,buf);
960 return buf.toString();
961 }
962
963
964
965
966
967
968
969 public static String toDetailString(ByteBuffer buffer)
970 {
971 if (buffer == null)
972 return "null";
973
974 StringBuilder buf = new StringBuilder();
975 idString(buffer,buf);
976 buf.append("[p=");
977 buf.append(buffer.position());
978 buf.append(",l=");
979 buf.append(buffer.limit());
980 buf.append(",c=");
981 buf.append(buffer.capacity());
982 buf.append(",r=");
983 buf.append(buffer.remaining());
984 buf.append("]={");
985
986 appendDebugString(buf,buffer);
987
988 buf.append("}");
989
990 return buf.toString();
991 }
992
993 private static void appendDebugString(StringBuilder buf,ByteBuffer buffer)
994 {
995 for (int i = 0; i < buffer.position(); i++)
996 {
997 appendContentChar(buf,buffer.get(i));
998 if (i == 16 && buffer.position() > 32)
999 {
1000 buf.append("...");
1001 i = buffer.position() - 16;
1002 }
1003 }
1004 buf.append("<<<");
1005 for (int i = buffer.position(); i < buffer.limit(); i++)
1006 {
1007 appendContentChar(buf,buffer.get(i));
1008 if (i == buffer.position() + 16 && buffer.limit() > buffer.position() + 32)
1009 {
1010 buf.append("...");
1011 i = buffer.limit() - 16;
1012 }
1013 }
1014 buf.append(">>>");
1015 int limit = buffer.limit();
1016 buffer.limit(buffer.capacity());
1017 for (int i = limit; i < buffer.capacity(); i++)
1018 {
1019 appendContentChar(buf,buffer.get(i));
1020 if (i == limit + 16 && buffer.capacity() > limit + 32)
1021 {
1022 buf.append("...");
1023 i = buffer.capacity() - 16;
1024 }
1025 }
1026 buffer.limit(limit);
1027 }
1028
1029 private static void appendContentChar(StringBuilder buf, byte b)
1030 {
1031 if (b == '\\')
1032 buf.append("\\\\");
1033 else if (b >= ' ')
1034 buf.append((char)b);
1035 else if (b == '\r')
1036 buf.append("\\r");
1037 else if (b == '\n')
1038 buf.append("\\n");
1039 else if (b == '\t')
1040 buf.append("\\t");
1041 else
1042 buf.append("\\x").append(TypeUtil.toHexString(b));
1043 }
1044
1045 private final static int[] decDivisors =
1046 {1000000000, 100000000, 10000000, 1000000, 100000, 10000, 1000, 100, 10, 1};
1047
1048 private final static int[] hexDivisors =
1049 {0x10000000, 0x1000000, 0x100000, 0x10000, 0x1000, 0x100, 0x10, 0x1};
1050
1051 private final static long[] decDivisorsL =
1052 {1000000000000000000L, 100000000000000000L, 10000000000000000L, 1000000000000000L, 100000000000000L, 10000000000000L, 1000000000000L, 100000000000L,
1053 10000000000L, 1000000000L, 100000000L, 10000000L, 1000000L, 100000L, 10000L, 1000L, 100L, 10L, 1L};
1054
1055 public static void putCRLF(ByteBuffer buffer)
1056 {
1057 buffer.put((byte)13);
1058 buffer.put((byte)10);
1059 }
1060
1061 public static boolean isPrefix(ByteBuffer prefix, ByteBuffer buffer)
1062 {
1063 if (prefix.remaining() > buffer.remaining())
1064 return false;
1065 int bi = buffer.position();
1066 for (int i = prefix.position(); i < prefix.limit(); i++)
1067 if (prefix.get(i) != buffer.get(bi++))
1068 return false;
1069 return true;
1070 }
1071
1072 public static ByteBuffer ensureCapacity(ByteBuffer buffer, int capacity)
1073 {
1074 if (buffer==null)
1075 return allocate(capacity);
1076
1077 if (buffer.capacity()>=capacity)
1078 return buffer;
1079
1080 if (buffer.hasArray())
1081 return ByteBuffer.wrap(Arrays.copyOfRange(buffer.array(), buffer.arrayOffset(), buffer.arrayOffset()+capacity),buffer.position(),buffer.remaining());
1082
1083 throw new UnsupportedOperationException();
1084 }
1085
1086
1087
1088 }