2 // ========================================================================
3 // Copyright (c) 1995-2016 Mort Bay Consulting Pty. Ltd.
4 // ------------------------------------------------------------------------
5 // All rights reserved. This program and the accompanying materials
6 // are made available under the terms of the Eclipse Public License v1.0
7 // and Apache License v2.0 which accompanies this distribution.
9 // The Eclipse Public License is available at
10 // http://www.eclipse.org/legal/epl-v10.html
12 // The Apache License v2.0 is available at
13 // http://www.opensource.org/licenses/apache2.0.php
15 // You may elect to redistribute this code under either of these licenses.
16 // ========================================================================
19 package org.eclipse.jetty.util;
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;
34 import org.eclipse.jetty.util.resource.Resource;
37 /* ------------------------------------------------------------------------------- */
39 * Buffer utility methods.
40 * <p>The standard JVM {@link ByteBuffer} can exist in two modes: In fill mode the valid
41 * data is between 0 and pos; In flush mode the valid data is between the pos and the limit.
42 * The various ByteBuffer methods assume a mode and some of them will switch or enforce a mode:
43 * Allocate and clear set fill mode; flip and compact switch modes; read and write assume fill
44 * and flush modes. This duality can result in confusing code such as:
47 * channel.write(buffer);
49 * Which looks as if it should write no data, but in fact writes the buffer worth of garbage.
52 * The BufferUtil class provides a set of utilities that operate on the convention that ByteBuffers
53 * will always be left, passed in an API or returned from a method in the flush mode - ie with
54 * valid data between the pos and limit. This convention is adopted so as to avoid confusion as to
55 * what state a buffer is in and to avoid excessive copying of data that can result with the usage
58 * Thus this class provides alternate implementations of {@link #allocate(int)},
59 * {@link #allocateDirect(int)} and {@link #clear(ByteBuffer)} that leave the buffer
60 * in flush mode. Thus the following tests will pass:<pre>
61 * ByteBuffer buffer = BufferUtil.allocate(1024);
62 * assert(buffer.remaining()==0);
63 * BufferUtil.clear(buffer);
64 * assert(buffer.remaining()==0);
67 * <p>If the BufferUtil methods {@link #fill(ByteBuffer, byte[], int, int)},
68 * {@link #append(ByteBuffer, byte[], int, int)} or {@link #put(ByteBuffer, ByteBuffer)} are used,
69 * then the caller does not need to explicitly switch the buffer to fill mode.
70 * If the caller wishes to use other ByteBuffer bases libraries to fill a buffer,
71 * then they can use explicit calls of #flipToFill(ByteBuffer) and #flipToFlush(ByteBuffer, int)
72 * to change modes. Note because this convention attempts to avoid the copies of compact, the position
73 * is not set to zero on each fill cycle and so its value must be remembered:
75 * int pos = BufferUtil.flipToFill(buffer);
82 * flipToFlush(buffer, pos);
85 * The flipToFill method will effectively clear the buffer if it is emtpy and will compact the buffer if there is no space.
88 public class BufferUtil
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'};
97 public static final ByteBuffer EMPTY_BUFFER = ByteBuffer.wrap(new byte[0]);
99 /* ------------------------------------------------------------ */
100 /** Allocate ByteBuffer in flush mode.
101 * The position and limit will both be zero, indicating that the buffer is
102 * empty and must be flipped before any data is put to it.
103 * @param capacity capacity of the allocated ByteBuffer
106 public static ByteBuffer allocate(int capacity)
108 ByteBuffer buf = ByteBuffer.allocate(capacity);
113 /* ------------------------------------------------------------ */
114 /** Allocate ByteBuffer in flush mode.
115 * The position and limit will both be zero, indicating that the buffer is
116 * empty and in flush mode.
117 * @param capacity capacity of the allocated ByteBuffer
120 public static ByteBuffer allocateDirect(int capacity)
122 ByteBuffer buf = ByteBuffer.allocateDirect(capacity);
128 /* ------------------------------------------------------------ */
129 /** Clear the buffer to be empty in flush mode.
130 * The position and limit are set to 0;
131 * @param buffer The buffer to clear.
133 public static void clear(ByteBuffer buffer)
142 /* ------------------------------------------------------------ */
143 /** Clear the buffer to be empty in fill mode.
144 * The position is set to 0 and the limit is set to the capacity.
145 * @param buffer The buffer to clear.
147 public static void clearToFill(ByteBuffer buffer)
152 buffer.limit(buffer.capacity());
156 /* ------------------------------------------------------------ */
157 /** Flip the buffer to fill mode.
158 * The position is set to the first unused position in the buffer
159 * (the old limit) and the limit is set to the capacity.
160 * If the buffer is empty, then this call is effectively {@link #clearToFill(ByteBuffer)}.
161 * If there is no unused space to fill, a {@link ByteBuffer#compact()} is done to attempt
164 * This method is used as a replacement to {@link ByteBuffer#compact()}.
166 * @param buffer The buffer to flip
167 * @return The position of the valid data before the flipped position. This value should be
168 * passed to a subsequent call to {@link #flipToFlush(ByteBuffer, int)}
170 public static int flipToFill(ByteBuffer buffer)
172 int position = buffer.position();
173 int limit = buffer.limit();
174 if (position == limit)
177 buffer.limit(buffer.capacity());
181 int capacity = buffer.capacity();
182 if (limit == capacity)
188 buffer.position(limit);
189 buffer.limit(capacity);
194 /* ------------------------------------------------------------ */
195 /** Flip the buffer to Flush mode.
196 * The limit is set to the first unused byte(the old position) and
197 * the position is set to the passed position.
199 * This method is used as a replacement of {@link Buffer#flip()}.
200 * @param buffer the buffer to be flipped
201 * @param position The position of valid data to flip to. This should
202 * be the return value of the previous call to {@link #flipToFill(ByteBuffer)}
204 public static void flipToFlush(ByteBuffer buffer, int position)
206 buffer.limit(buffer.position());
207 buffer.position(position);
211 /* ------------------------------------------------------------ */
212 /** Convert a ByteBuffer to a byte array.
213 * @param buffer The buffer to convert in flush mode. The buffer is not altered.
214 * @return An array of bytes duplicated from the buffer.
216 public static byte[] toArray(ByteBuffer buffer)
218 if (buffer.hasArray())
220 byte[] array = buffer.array();
221 int from=buffer.arrayOffset() + buffer.position();
222 return Arrays.copyOfRange(array,from,from+buffer.remaining());
226 byte[] to = new byte[buffer.remaining()];
227 buffer.slice().get(to);
232 /* ------------------------------------------------------------ */
233 /** Check for an empty or null buffer.
234 * @param buf the buffer to check
235 * @return true if the buffer is null or empty.
237 public static boolean isEmpty(ByteBuffer buf)
239 return buf == null || buf.remaining() == 0;
242 /* ------------------------------------------------------------ */
243 /** Check for a non null and non empty buffer.
244 * @param buf the buffer to check
245 * @return true if the buffer is not null and not empty.
247 public static boolean hasContent(ByteBuffer buf)
249 return buf != null && buf.remaining() > 0;
252 /* ------------------------------------------------------------ */
253 /** Check for a non null and full buffer.
254 * @param buf the buffer to check
255 * @return true if the buffer is not null and the limit equals the capacity.
257 public static boolean isFull(ByteBuffer buf)
259 return buf != null && buf.limit() == buf.capacity();
262 /* ------------------------------------------------------------ */
263 /** Get remaining from null checked buffer
264 * @param buffer The buffer to get the remaining from, in flush mode.
265 * @return 0 if the buffer is null, else the bytes remaining in the buffer.
267 public static int length(ByteBuffer buffer)
269 return buffer == null ? 0 : buffer.remaining();
272 /* ------------------------------------------------------------ */
273 /** Get the space from the limit to the capacity
274 * @param buffer the buffer to get the space from
277 public static int space(ByteBuffer buffer)
281 return buffer.capacity() - buffer.limit();
284 /* ------------------------------------------------------------ */
285 /** Compact the buffer
286 * @param buffer the buffer to compact
287 * @return true if the compact made a full buffer have space
289 public static boolean compact(ByteBuffer buffer)
291 if (buffer.position()==0)
293 boolean full = buffer.limit() == buffer.capacity();
294 buffer.compact().flip();
295 return full && buffer.limit() < buffer.capacity();
298 /* ------------------------------------------------------------ */
300 * Put data from one buffer into another, avoiding over/under flows
301 * @param from Buffer to take bytes from in flush mode
302 * @param to Buffer to put bytes to in fill mode.
303 * @return number of bytes moved
305 public static int put(ByteBuffer from, ByteBuffer to)
308 int remaining = from.remaining();
311 if (remaining <= to.remaining())
318 else if (from.hasArray())
320 put = to.remaining();
321 to.put(from.array(), from.arrayOffset() + from.position(), put);
322 from.position(from.position() + put);
326 put = to.remaining();
327 ByteBuffer slice = from.slice();
330 from.position(from.position() + put);
339 /* ------------------------------------------------------------ */
341 * Put data from one buffer into another, avoiding over/under flows
342 * @param from Buffer to take bytes from in flush mode
343 * @param to Buffer to put bytes to in flush mode. The buffer is flipToFill before the put and flipToFlush after.
344 * @return number of bytes moved
345 * @deprecated use {@link #append(ByteBuffer, ByteBuffer)}
347 public static int flipPutFlip(ByteBuffer from, ByteBuffer to)
349 return append(to,from);
352 /* ------------------------------------------------------------ */
353 /** Append bytes to a buffer.
354 * @param to Buffer is flush mode
355 * @param b bytes to append
356 * @param off offset into byte
357 * @param len length to append
358 * @throws BufferOverflowException
360 public static void append(ByteBuffer to, byte[] b, int off, int len) throws BufferOverflowException
362 int pos = flipToFill(to);
369 flipToFlush(to, pos);
373 /* ------------------------------------------------------------ */
374 /** Appends a byte to a buffer
375 * @param to Buffer is flush mode
376 * @param b byte to append
378 public static void append(ByteBuffer to, byte b)
380 int pos = flipToFill(to);
387 flipToFlush(to, pos);
391 /* ------------------------------------------------------------ */
392 /** Appends a buffer to a buffer
393 * @param to Buffer is flush mode
394 * @param b buffer to append
396 public static int append(ByteBuffer to, ByteBuffer b)
398 int pos = flipToFill(to);
405 flipToFlush(to, pos);
409 /* ------------------------------------------------------------ */
411 * Like append, but does not throw {@link BufferOverflowException}
412 * @param to Buffer is flush mode
413 * @param b bytes to fill
414 * @param off offset into byte
415 * @param len length to fill
417 public static int fill(ByteBuffer to, byte[] b, int off, int len)
419 int pos = flipToFill(to);
422 int remaining = to.remaining();
423 int take = remaining < len ? remaining : len;
424 to.put(b, off, take);
429 flipToFlush(to, pos);
434 /* ------------------------------------------------------------ */
435 public static void readFrom(File file, ByteBuffer buffer) throws IOException
437 try(RandomAccessFile raf = new RandomAccessFile(file,"r"))
439 FileChannel channel = raf.getChannel();
440 long needed=raf.length();
442 while (needed>0 && buffer.hasRemaining())
443 needed=needed-channel.read(buffer);
447 /* ------------------------------------------------------------ */
448 public static void readFrom(InputStream is, int needed, ByteBuffer buffer) throws IOException
450 ByteBuffer tmp = allocate(8192);
452 while (needed > 0 && buffer.hasRemaining())
454 int l = is.read(tmp.array(), 0, 8192);
463 /* ------------------------------------------------------------ */
464 public static void writeTo(ByteBuffer buffer, OutputStream out) throws IOException
466 if (buffer.hasArray())
468 out.write(buffer.array(),buffer.arrayOffset() + buffer.position(),buffer.remaining());
469 // update buffer position, in way similar to non-array version of writeTo
470 buffer.position(buffer.position() + buffer.remaining());
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);
483 /* ------------------------------------------------------------ */
484 /** Convert the buffer to an ISO-8859-1 String
485 * @param buffer The buffer to convert in flush mode. The buffer is unchanged
486 * @return The buffer as a string.
488 public static String toString(ByteBuffer buffer)
490 return toString(buffer, StandardCharsets.ISO_8859_1);
493 /* ------------------------------------------------------------ */
494 /** Convert the buffer to an UTF-8 String
495 * @param buffer The buffer to convert in flush mode. The buffer is unchanged
496 * @return The buffer as a string.
498 public static String toUTF8String(ByteBuffer buffer)
500 return toString(buffer, StandardCharsets.UTF_8);
503 /* ------------------------------------------------------------ */
504 /** Convert the buffer to an ISO-8859-1 String
505 * @param buffer The buffer to convert in flush mode. The buffer is unchanged
506 * @param charset The {@link Charset} to use to convert the bytes
507 * @return The buffer as a string.
509 public static String toString(ByteBuffer buffer, Charset charset)
513 byte[] array = buffer.hasArray() ? buffer.array() : null;
516 byte[] to = new byte[buffer.remaining()];
517 buffer.slice().get(to);
518 return new String(to, 0, to.length, charset);
520 return new String(array, buffer.arrayOffset() + buffer.position(), buffer.remaining(), charset);
523 /* ------------------------------------------------------------ */
524 /** Convert a partial buffer to an ISO-8859-1 String
525 * @param buffer The buffer to convert in flush mode. The buffer is unchanged
526 * @param charset The {@link Charset} to use to convert the bytes
527 * @return The buffer as a string.
529 public static String toString(ByteBuffer buffer, int position, int length, Charset charset)
533 byte[] array = buffer.hasArray() ? buffer.array() : null;
536 ByteBuffer ro = buffer.asReadOnlyBuffer();
537 ro.position(position);
538 ro.limit(position + length);
539 byte[] to = new byte[length];
541 return new String(to, 0, to.length, charset);
543 return new String(array, buffer.arrayOffset() + position, length, charset);
546 /* ------------------------------------------------------------ */
548 * Convert buffer to an integer. Parses up to the first non-numeric character. If no number is found an IllegalArgumentException is thrown
551 * A buffer containing an integer in flush mode. The position is not changed.
554 public static int toInt(ByteBuffer buffer)
557 boolean started = false;
558 boolean minus = false;
560 for (int i = buffer.position(); i < buffer.limit(); i++)
562 byte b = buffer.get(i);
568 else if (b >= '0' && b <= '9')
570 val = val * 10 + (b - '0');
573 else if (b == MINUS && !started)
582 return minus ? (-val) : val;
583 throw new NumberFormatException(toString(buffer));
586 /* ------------------------------------------------------------ */
588 * Convert buffer to an integer. Parses up to the first non-numeric character. If no number is found an IllegalArgumentException is thrown
591 * A buffer containing an integer in flush mode. The position is updated.
594 public static int takeInt(ByteBuffer buffer)
597 boolean started = false;
598 boolean minus = false;
600 for (i = buffer.position(); i < buffer.limit(); i++)
602 byte b = buffer.get(i);
608 else if (b >= '0' && b <= '9')
610 val = val * 10 + (b - '0');
613 else if (b == MINUS && !started)
624 return minus ? (-val) : val;
626 throw new NumberFormatException(toString(buffer));
630 * Convert buffer to an long. Parses up to the first non-numeric character. If no number is found an IllegalArgumentException is thrown
633 * A buffer containing an integer in flush mode. The position is not changed.
636 public static long toLong(ByteBuffer buffer)
639 boolean started = false;
640 boolean minus = false;
642 for (int i = buffer.position(); i < buffer.limit(); i++)
644 byte b = buffer.get(i);
650 else if (b >= '0' && b <= '9')
652 val = val * 10L + (b - '0');
655 else if (b == MINUS && !started)
664 return minus ? (-val) : val;
665 throw new NumberFormatException(toString(buffer));
668 public static void putHexInt(ByteBuffer buffer, int n)
672 buffer.put((byte)'-');
674 if (n == Integer.MIN_VALUE)
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'));
692 buffer.put(DIGIT[n]);
696 boolean started = false;
697 // This assumes constant time int arithmatic
698 for (int hexDivisor : hexDivisors)
703 buffer.put((byte)'0');
708 int d = n / hexDivisor;
709 buffer.put(DIGIT[d]);
710 n = n - d * hexDivisor;
715 /* ------------------------------------------------------------ */
716 public static void putDecInt(ByteBuffer buffer, int n)
720 buffer.put((byte)'-');
722 if (n == Integer.MIN_VALUE)
724 buffer.put((byte)'2');
733 buffer.put(DIGIT[n]);
737 boolean started = false;
738 // This assumes constant time int arithmatic
739 for (int decDivisor : decDivisors)
744 buffer.put((byte)'0');
749 int d = n / decDivisor;
750 buffer.put(DIGIT[d]);
751 n = n - d * decDivisor;
756 public static void putDecLong(ByteBuffer buffer, long n)
760 buffer.put((byte)'-');
762 if (n == Long.MIN_VALUE)
764 buffer.put((byte)'9');
765 n = 223372036854775808L;
773 buffer.put(DIGIT[(int)n]);
777 boolean started = false;
778 // This assumes constant time int arithmatic
779 for (long aDecDivisorsL : decDivisorsL)
781 if (n < aDecDivisorsL)
784 buffer.put((byte)'0');
789 long d = n / aDecDivisorsL;
790 buffer.put(DIGIT[(int)d]);
791 n = n - d * aDecDivisorsL;
796 public static ByteBuffer toBuffer(int value)
798 ByteBuffer buf = ByteBuffer.allocate(32);
799 putDecInt(buf, value);
803 public static ByteBuffer toBuffer(long value)
805 ByteBuffer buf = ByteBuffer.allocate(32);
806 putDecLong(buf, value);
810 public static ByteBuffer toBuffer(String s)
812 return ByteBuffer.wrap(s.getBytes(StandardCharsets.ISO_8859_1));
815 public static ByteBuffer toDirectBuffer(String s)
817 byte[] bytes = s.getBytes(StandardCharsets.ISO_8859_1);
818 ByteBuffer buf = ByteBuffer.allocateDirect(bytes.length);
824 public static ByteBuffer toBuffer(String s, Charset charset)
826 return ByteBuffer.wrap(s.getBytes(charset));
829 public static ByteBuffer toDirectBuffer(String s, Charset charset)
831 byte[] bytes = s.getBytes(charset);
832 ByteBuffer buf = ByteBuffer.allocateDirect(bytes.length);
839 * Create a new ByteBuffer using provided byte array.
842 * the byte array to back buffer with.
843 * @return ByteBuffer with provided byte array, in flush mode
845 public static ByteBuffer toBuffer(byte array[])
847 return ByteBuffer.wrap(array);
851 * Create a new ByteBuffer using the provided byte array.
854 * the byte array to use.
856 * the offset within the byte array to use from
858 * the length in bytes of the array to use
859 * @return ByteBuffer with provided byte array, in flush mode
861 public static ByteBuffer toBuffer(byte array[], int offset, int length)
863 return ByteBuffer.wrap(array, offset, length);
866 public static ByteBuffer toMappedBuffer(File file) throws IOException
868 try (RandomAccessFile raf = new RandomAccessFile(file, "r"))
870 return raf.getChannel().map(MapMode.READ_ONLY, 0, raf.length());
874 public static ByteBuffer toBuffer(Resource resource,boolean direct) throws IOException
876 int len=(int)resource.length();
878 throw new IllegalArgumentException("invalid resource: "+String.valueOf(resource)+" len="+len);
880 ByteBuffer buffer = direct?BufferUtil.allocateDirect(len):BufferUtil.allocate(len);
882 int pos=BufferUtil.flipToFill(buffer);
883 if (resource.getFile()!=null)
884 BufferUtil.readFrom(resource.getFile(),buffer);
887 try (InputStream is = resource.getInputStream();)
889 BufferUtil.readFrom(is,len,buffer);
892 BufferUtil.flipToFlush(buffer,pos);
897 public static String toSummaryString(ByteBuffer buffer)
901 StringBuilder buf = new StringBuilder();
903 buf.append(buffer.position());
905 buf.append(buffer.limit());
907 buf.append(buffer.capacity());
909 buf.append(buffer.remaining());
911 return buf.toString();
914 public static String toDetailString(ByteBuffer[] buffer)
916 StringBuilder builder = new StringBuilder();
918 for (int i = 0; i < buffer.length; i++)
920 if (i > 0) builder.append(',');
921 builder.append(toDetailString(buffer[i]));
924 return builder.toString();
929 /* ------------------------------------------------------------ */
930 /** Convert Buffer to string ID independent of content
933 private static void idString(ByteBuffer buffer, StringBuilder out)
935 out.append(buffer.getClass().getSimpleName());
937 if (buffer.hasArray() && buffer.arrayOffset()==4)
940 byte[] array = buffer.array();
941 TypeUtil.toHex(array[0],out);
942 TypeUtil.toHex(array[1],out);
943 TypeUtil.toHex(array[2],out);
944 TypeUtil.toHex(array[3],out);
947 out.append(Integer.toHexString(System.identityHashCode(buffer)));
950 /* ------------------------------------------------------------ */
951 /** Convert Buffer to string ID independent of content
953 * @return A string showing the buffer ID
955 public static String toIDString(ByteBuffer buffer)
957 StringBuilder buf = new StringBuilder();
958 idString(buffer,buf);
959 return buf.toString();
963 /* ------------------------------------------------------------ */
964 /** Convert Buffer to a detail debug string of pointers and content
966 * @return A string showing the pointers and content of the buffer
968 public static String toDetailString(ByteBuffer buffer)
973 StringBuilder buf = new StringBuilder();
974 idString(buffer,buf);
976 buf.append(buffer.position());
978 buf.append(buffer.limit());
980 buf.append(buffer.capacity());
982 buf.append(buffer.remaining());
985 appendDebugString(buf,buffer);
989 return buf.toString();
992 private static void appendDebugString(StringBuilder buf,ByteBuffer buffer)
994 for (int i = 0; i < buffer.position(); i++)
996 appendContentChar(buf,buffer.get(i));
997 if (i == 16 && buffer.position() > 32)
1000 i = buffer.position() - 16;
1004 for (int i = buffer.position(); i < buffer.limit(); i++)
1006 appendContentChar(buf,buffer.get(i));
1007 if (i == buffer.position() + 16 && buffer.limit() > buffer.position() + 32)
1010 i = buffer.limit() - 16;
1014 int limit = buffer.limit();
1015 buffer.limit(buffer.capacity());
1016 for (int i = limit; i < buffer.capacity(); i++)
1018 appendContentChar(buf,buffer.get(i));
1019 if (i == limit + 16 && buffer.capacity() > limit + 32)
1022 i = buffer.capacity() - 16;
1025 buffer.limit(limit);
1028 private static void appendContentChar(StringBuilder buf, byte b)
1033 buf.append((char)b);
1041 buf.append("\\x").append(TypeUtil.toHexString(b));
1044 private final static int[] decDivisors =
1045 {1000000000, 100000000, 10000000, 1000000, 100000, 10000, 1000, 100, 10, 1};
1047 private final static int[] hexDivisors =
1048 {0x10000000, 0x1000000, 0x100000, 0x10000, 0x1000, 0x100, 0x10, 0x1};
1050 private final static long[] decDivisorsL =
1051 {1000000000000000000L, 100000000000000000L, 10000000000000000L, 1000000000000000L, 100000000000000L, 10000000000000L, 1000000000000L, 100000000000L,
1052 10000000000L, 1000000000L, 100000000L, 10000000L, 1000000L, 100000L, 10000L, 1000L, 100L, 10L, 1L};
1054 public static void putCRLF(ByteBuffer buffer)
1056 buffer.put((byte)13);
1057 buffer.put((byte)10);
1060 public static boolean isPrefix(ByteBuffer prefix, ByteBuffer buffer)
1062 if (prefix.remaining() > buffer.remaining())
1064 int bi = buffer.position();
1065 for (int i = prefix.position(); i < prefix.limit(); i++)
1066 if (prefix.get(i) != buffer.get(bi++))
1071 public static ByteBuffer ensureCapacity(ByteBuffer buffer, int capacity)
1074 return allocate(capacity);
1076 if (buffer.capacity()>=capacity)
1079 if (buffer.hasArray())
1080 return ByteBuffer.wrap(Arrays.copyOfRange(buffer.array(), buffer.arrayOffset(), buffer.arrayOffset()+capacity),buffer.position(),buffer.remaining());
1082 throw new UnsupportedOperationException();