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