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