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