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 out.write(buffer.array(), buffer.arrayOffset() + buffer.position(), buffer.remaining());
468 else
469 {
470 byte[] bytes = new byte[TEMP_BUFFER_SIZE];
471 while(buffer.hasRemaining()){
472 int byteCountToWrite = Math.min(buffer.remaining(), TEMP_BUFFER_SIZE);
473 buffer.get(bytes, 0, byteCountToWrite);
474 out.write(bytes,0 , byteCountToWrite);
475 }
476 }
477 }
478
479
480
481
482
483
484 public static String toString(ByteBuffer buffer)
485 {
486 return toString(buffer, StandardCharsets.ISO_8859_1);
487 }
488
489
490
491
492
493
494 public static String toUTF8String(ByteBuffer buffer)
495 {
496 return toString(buffer, StandardCharsets.UTF_8);
497 }
498
499
500
501
502
503
504
505 public static String toString(ByteBuffer buffer, Charset charset)
506 {
507 if (buffer == null)
508 return null;
509 byte[] array = buffer.hasArray() ? buffer.array() : null;
510 if (array == null)
511 {
512 byte[] to = new byte[buffer.remaining()];
513 buffer.slice().get(to);
514 return new String(to, 0, to.length, charset);
515 }
516 return new String(array, buffer.arrayOffset() + buffer.position(), buffer.remaining(), charset);
517 }
518
519
520
521
522
523
524
525 public static String toString(ByteBuffer buffer, int position, int length, Charset charset)
526 {
527 if (buffer == null)
528 return null;
529 byte[] array = buffer.hasArray() ? buffer.array() : null;
530 if (array == null)
531 {
532 ByteBuffer ro = buffer.asReadOnlyBuffer();
533 ro.position(position);
534 ro.limit(position + length);
535 byte[] to = new byte[length];
536 ro.get(to);
537 return new String(to, 0, to.length, charset);
538 }
539 return new String(array, buffer.arrayOffset() + position, length, charset);
540 }
541
542
543
544
545
546
547
548
549
550 public static int toInt(ByteBuffer buffer)
551 {
552 int val = 0;
553 boolean started = false;
554 boolean minus = false;
555
556 for (int i = buffer.position(); i < buffer.limit(); i++)
557 {
558 byte b = buffer.get(i);
559 if (b <= SPACE)
560 {
561 if (started)
562 break;
563 }
564 else if (b >= '0' && b <= '9')
565 {
566 val = val * 10 + (b - '0');
567 started = true;
568 }
569 else if (b == MINUS && !started)
570 {
571 minus = true;
572 }
573 else
574 break;
575 }
576
577 if (started)
578 return minus ? (-val) : val;
579 throw new NumberFormatException(toString(buffer));
580 }
581
582
583
584
585
586
587
588
589
590 public static int takeInt(ByteBuffer buffer)
591 {
592 int val = 0;
593 boolean started = false;
594 boolean minus = false;
595 int i;
596 for (i = buffer.position(); i < buffer.limit(); i++)
597 {
598 byte b = buffer.get(i);
599 if (b <= SPACE)
600 {
601 if (started)
602 break;
603 }
604 else if (b >= '0' && b <= '9')
605 {
606 val = val * 10 + (b - '0');
607 started = true;
608 }
609 else if (b == MINUS && !started)
610 {
611 minus = true;
612 }
613 else
614 break;
615 }
616
617 if (started)
618 {
619 buffer.position(i);
620 return minus ? (-val) : val;
621 }
622 throw new NumberFormatException(toString(buffer));
623 }
624
625
626
627
628
629
630
631
632 public static long toLong(ByteBuffer buffer)
633 {
634 long val = 0;
635 boolean started = false;
636 boolean minus = false;
637
638 for (int i = buffer.position(); i < buffer.limit(); i++)
639 {
640 byte b = buffer.get(i);
641 if (b <= SPACE)
642 {
643 if (started)
644 break;
645 }
646 else if (b >= '0' && b <= '9')
647 {
648 val = val * 10L + (b - '0');
649 started = true;
650 }
651 else if (b == MINUS && !started)
652 {
653 minus = true;
654 }
655 else
656 break;
657 }
658
659 if (started)
660 return minus ? (-val) : val;
661 throw new NumberFormatException(toString(buffer));
662 }
663
664 public static void putHexInt(ByteBuffer buffer, int n)
665 {
666 if (n < 0)
667 {
668 buffer.put((byte)'-');
669
670 if (n == Integer.MIN_VALUE)
671 {
672 buffer.put((byte)(0x7f & '8'));
673 buffer.put((byte)(0x7f & '0'));
674 buffer.put((byte)(0x7f & '0'));
675 buffer.put((byte)(0x7f & '0'));
676 buffer.put((byte)(0x7f & '0'));
677 buffer.put((byte)(0x7f & '0'));
678 buffer.put((byte)(0x7f & '0'));
679 buffer.put((byte)(0x7f & '0'));
680
681 return;
682 }
683 n = -n;
684 }
685
686 if (n < 0x10)
687 {
688 buffer.put(DIGIT[n]);
689 }
690 else
691 {
692 boolean started = false;
693
694 for (int hexDivisor : hexDivisors)
695 {
696 if (n < hexDivisor)
697 {
698 if (started)
699 buffer.put((byte)'0');
700 continue;
701 }
702
703 started = true;
704 int d = n / hexDivisor;
705 buffer.put(DIGIT[d]);
706 n = n - d * hexDivisor;
707 }
708 }
709 }
710
711
712 public static void putDecInt(ByteBuffer buffer, int n)
713 {
714 if (n < 0)
715 {
716 buffer.put((byte)'-');
717
718 if (n == Integer.MIN_VALUE)
719 {
720 buffer.put((byte)'2');
721 n = 147483648;
722 }
723 else
724 n = -n;
725 }
726
727 if (n < 10)
728 {
729 buffer.put(DIGIT[n]);
730 }
731 else
732 {
733 boolean started = false;
734
735 for (int decDivisor : decDivisors)
736 {
737 if (n < decDivisor)
738 {
739 if (started)
740 buffer.put((byte)'0');
741 continue;
742 }
743
744 started = true;
745 int d = n / decDivisor;
746 buffer.put(DIGIT[d]);
747 n = n - d * decDivisor;
748 }
749 }
750 }
751
752 public static void putDecLong(ByteBuffer buffer, long n)
753 {
754 if (n < 0)
755 {
756 buffer.put((byte)'-');
757
758 if (n == Long.MIN_VALUE)
759 {
760 buffer.put((byte)'9');
761 n = 223372036854775808L;
762 }
763 else
764 n = -n;
765 }
766
767 if (n < 10)
768 {
769 buffer.put(DIGIT[(int)n]);
770 }
771 else
772 {
773 boolean started = false;
774
775 for (long aDecDivisorsL : decDivisorsL)
776 {
777 if (n < aDecDivisorsL)
778 {
779 if (started)
780 buffer.put((byte)'0');
781 continue;
782 }
783
784 started = true;
785 long d = n / aDecDivisorsL;
786 buffer.put(DIGIT[(int)d]);
787 n = n - d * aDecDivisorsL;
788 }
789 }
790 }
791
792 public static ByteBuffer toBuffer(int value)
793 {
794 ByteBuffer buf = ByteBuffer.allocate(32);
795 putDecInt(buf, value);
796 return buf;
797 }
798
799 public static ByteBuffer toBuffer(long value)
800 {
801 ByteBuffer buf = ByteBuffer.allocate(32);
802 putDecLong(buf, value);
803 return buf;
804 }
805
806 public static ByteBuffer toBuffer(String s)
807 {
808 return ByteBuffer.wrap(s.getBytes(StandardCharsets.ISO_8859_1));
809 }
810
811 public static ByteBuffer toDirectBuffer(String s)
812 {
813 byte[] bytes = s.getBytes(StandardCharsets.ISO_8859_1);
814 ByteBuffer buf = ByteBuffer.allocateDirect(bytes.length);
815 buf.put(bytes);
816 buf.flip();
817 return buf;
818 }
819
820 public static ByteBuffer toBuffer(String s, Charset charset)
821 {
822 return ByteBuffer.wrap(s.getBytes(charset));
823 }
824
825 public static ByteBuffer toDirectBuffer(String s, Charset charset)
826 {
827 byte[] bytes = s.getBytes(charset);
828 ByteBuffer buf = ByteBuffer.allocateDirect(bytes.length);
829 buf.put(bytes);
830 buf.flip();
831 return buf;
832 }
833
834
835
836
837
838
839
840
841 public static ByteBuffer toBuffer(byte array[])
842 {
843 return ByteBuffer.wrap(array);
844 }
845
846
847
848
849
850
851
852
853
854
855
856
857 public static ByteBuffer toBuffer(byte array[], int offset, int length)
858 {
859 return ByteBuffer.wrap(array, offset, length);
860 }
861
862 public static ByteBuffer toMappedBuffer(File file) throws IOException
863 {
864 try (RandomAccessFile raf = new RandomAccessFile(file, "r"))
865 {
866 return raf.getChannel().map(MapMode.READ_ONLY, 0, raf.length());
867 }
868 }
869
870 public static ByteBuffer toBuffer(Resource resource,boolean direct) throws IOException
871 {
872 int len=(int)resource.length();
873 if (len<0)
874 throw new IllegalArgumentException("invalid resource: "+String.valueOf(resource)+" len="+len);
875
876 ByteBuffer buffer = direct?BufferUtil.allocateDirect(len):BufferUtil.allocate(len);
877
878 int pos=BufferUtil.flipToFill(buffer);
879 if (resource.getFile()!=null)
880 BufferUtil.readFrom(resource.getFile(),buffer);
881 else
882 {
883 try (InputStream is = resource.getInputStream();)
884 {
885 BufferUtil.readFrom(is,len,buffer);
886 }
887 }
888 BufferUtil.flipToFlush(buffer,pos);
889
890 return buffer;
891 }
892
893 public static String toSummaryString(ByteBuffer buffer)
894 {
895 if (buffer == null)
896 return "null";
897 StringBuilder buf = new StringBuilder();
898 buf.append("[p=");
899 buf.append(buffer.position());
900 buf.append(",l=");
901 buf.append(buffer.limit());
902 buf.append(",c=");
903 buf.append(buffer.capacity());
904 buf.append(",r=");
905 buf.append(buffer.remaining());
906 buf.append("]");
907 return buf.toString();
908 }
909
910 public static String toDetailString(ByteBuffer[] buffer)
911 {
912 StringBuilder builder = new StringBuilder();
913 builder.append('[');
914 for (int i = 0; i < buffer.length; i++)
915 {
916 if (i > 0) builder.append(',');
917 builder.append(toDetailString(buffer[i]));
918 }
919 builder.append(']');
920 return builder.toString();
921 }
922
923
924
925
926
927
928 public static String toDetailString(ByteBuffer buffer)
929 {
930 if (buffer == null)
931 return "null";
932
933 StringBuilder buf = new StringBuilder();
934 buf.append(buffer.getClass().getSimpleName());
935 buf.append("@");
936 if (buffer.hasArray())
937 buf.append(Integer.toHexString(Arrays.hashCode(buffer.array())));
938 else
939 buf.append(Integer.toHexString(buf.hashCode()));
940 buf.append("[p=");
941 buf.append(buffer.position());
942 buf.append(",l=");
943 buf.append(buffer.limit());
944 buf.append(",c=");
945 buf.append(buffer.capacity());
946 buf.append(",r=");
947 buf.append(buffer.remaining());
948 buf.append("]={");
949
950 appendDebugString(buf,buffer);
951
952 buf.append("}");
953
954 return buf.toString();
955 }
956
957
958
959
960
961
962
963 public static String toDebugString(ByteBuffer buffer)
964 {
965 if (buffer == null)
966 return "null";
967 StringBuilder buf = new StringBuilder();
968 appendDebugString(buf,buffer);
969 return buf.toString();
970 }
971
972 private static void appendDebugString(StringBuilder buf,ByteBuffer buffer)
973 {
974 for (int i = 0; i < buffer.position(); i++)
975 {
976 appendContentChar(buf,buffer.get(i));
977 if (i == 16 && buffer.position() > 32)
978 {
979 buf.append("...");
980 i = buffer.position() - 16;
981 }
982 }
983 buf.append("<<<");
984 for (int i = buffer.position(); i < buffer.limit(); i++)
985 {
986 appendContentChar(buf,buffer.get(i));
987 if (i == buffer.position() + 16 && buffer.limit() > buffer.position() + 32)
988 {
989 buf.append("...");
990 i = buffer.limit() - 16;
991 }
992 }
993 buf.append(">>>");
994 int limit = buffer.limit();
995 buffer.limit(buffer.capacity());
996 for (int i = limit; i < buffer.capacity(); i++)
997 {
998 appendContentChar(buf,buffer.get(i));
999 if (i == limit + 16 && buffer.capacity() > limit + 32)
1000 {
1001 buf.append("...");
1002 i = buffer.capacity() - 16;
1003 }
1004 }
1005 buffer.limit(limit);
1006 }
1007
1008 private static void appendContentChar(StringBuilder buf, byte b)
1009 {
1010 if (b == '\\')
1011 buf.append("\\\\");
1012 else if (b >= ' ')
1013 buf.append((char)b);
1014 else if (b == '\r')
1015 buf.append("\\r");
1016 else if (b == '\n')
1017 buf.append("\\n");
1018 else if (b == '\t')
1019 buf.append("\\t");
1020 else
1021 buf.append("\\x").append(TypeUtil.toHexString(b));
1022 }
1023
1024 private final static int[] decDivisors =
1025 {1000000000, 100000000, 10000000, 1000000, 100000, 10000, 1000, 100, 10, 1};
1026
1027 private final static int[] hexDivisors =
1028 {0x10000000, 0x1000000, 0x100000, 0x10000, 0x1000, 0x100, 0x10, 0x1};
1029
1030 private final static long[] decDivisorsL =
1031 {1000000000000000000L, 100000000000000000L, 10000000000000000L, 1000000000000000L, 100000000000000L, 10000000000000L, 1000000000000L, 100000000000L,
1032 10000000000L, 1000000000L, 100000000L, 10000000L, 1000000L, 100000L, 10000L, 1000L, 100L, 10L, 1L};
1033
1034 public static void putCRLF(ByteBuffer buffer)
1035 {
1036 buffer.put((byte)13);
1037 buffer.put((byte)10);
1038 }
1039
1040 public static boolean isPrefix(ByteBuffer prefix, ByteBuffer buffer)
1041 {
1042 if (prefix.remaining() > buffer.remaining())
1043 return false;
1044 int bi = buffer.position();
1045 for (int i = prefix.position(); i < prefix.limit(); i++)
1046 if (prefix.get(i) != buffer.get(bi++))
1047 return false;
1048 return true;
1049 }
1050
1051 public static ByteBuffer ensureCapacity(ByteBuffer buffer, int capacity)
1052 {
1053 if (buffer==null)
1054 return allocate(capacity);
1055
1056 if (buffer.capacity()>=capacity)
1057 return buffer;
1058
1059 if (buffer.hasArray())
1060 return ByteBuffer.wrap(Arrays.copyOfRange(buffer.array(), buffer.arrayOffset(), buffer.arrayOffset()+capacity),buffer.position(),buffer.remaining());
1061
1062 throw new UnsupportedOperationException();
1063 }
1064
1065
1066
1067 }