2 // ========================================================================
3 // Copyright (c) 1995-2014 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.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 import java.util.Arrays;
35 import org.eclipse.jetty.util.resource.Resource;
38 /* ------------------------------------------------------------------------------- */
40 * Buffer utility methods.
41 * <p>The standard JVM {@link ByteBuffer} can exist in two modes: In fill mode the valid
42 * data is between 0 and pos; In flush mode the valid data is between the pos and the limit.
43 * The various ByteBuffer methods assume a mode and some of them will switch or enforce a mode:
44 * Allocate and clear set fill mode; flip and compact switch modes; read and write assume fill
45 * and flush modes. This duality can result in confusing code such as:
48 * channel.write(buffer);
50 * Which looks as if it should write no data, but in fact writes the buffer worth of garbage.
53 * The BufferUtil class provides a set of utilities that operate on the convention that ByteBuffers
54 * will always be left, passed in an API or returned from a method in the flush mode - ie with
55 * valid data between the pos and limit. This convention is adopted so as to avoid confusion as to
56 * what state a buffer is in and to avoid excessive copying of data that can result with the usage
59 * Thus this class provides alternate implementations of {@link #allocate(int)},
60 * {@link #allocateDirect(int)} and {@link #clear(ByteBuffer)} that leave the buffer
61 * in flush mode. Thus the following tests will pass:<pre>
62 * ByteBuffer buffer = BufferUtil.allocate(1024);
63 * assert(buffer.remaining()==0);
64 * BufferUtil.clear(buffer);
65 * assert(buffer.remaining()==0);
68 * <p>If the BufferUtil methods {@link #fill(ByteBuffer, byte[], int, int)},
69 * {@link #append(ByteBuffer, byte[], int, int)} or {@link #put(ByteBuffer, ByteBuffer)} are used,
70 * then the caller does not need to explicitly switch the buffer to fill mode.
71 * If the caller wishes to use other ByteBuffer bases libraries to fill a buffer,
72 * then they can use explicit calls of #flipToFill(ByteBuffer) and #flipToFlush(ByteBuffer, int)
73 * to change modes. Note because this convention attempts to avoid the copies of compact, the position
74 * is not set to zero on each fill cycle and so its value must be remembered:
76 * int pos = BufferUtil.flipToFill(buffer);
83 * flipToFlush(buffer, pos);
86 * The flipToFill method will effectively clear the buffer if it is emtpy and will compact the buffer if there is no space.
89 public class BufferUtil
91 static final int TEMP_BUFFER_SIZE = 4096;
92 static final byte SPACE = 0x20;
93 static final byte MINUS = '-';
94 static final byte[] DIGIT =
95 {(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',
96 (byte)'E', (byte)'F'};
98 public static final ByteBuffer EMPTY_BUFFER = ByteBuffer.wrap(new byte[0]);
100 /* ------------------------------------------------------------ */
101 /** Allocate ByteBuffer in flush mode.
102 * The position and limit will both be zero, indicating that the buffer is
103 * empty and must be flipped before any data is put to it.
104 * @param capacity capacity of the allocated ByteBuffer
107 public static ByteBuffer allocate(int capacity)
109 ByteBuffer buf = ByteBuffer.allocate(capacity);
114 /* ------------------------------------------------------------ */
115 /** Allocate ByteBuffer in flush mode.
116 * The position and limit will both be zero, indicating that the buffer is
117 * empty and in flush mode.
118 * @param capacity capacity of the allocated ByteBuffer
121 public static ByteBuffer allocateDirect(int capacity)
123 ByteBuffer buf = ByteBuffer.allocateDirect(capacity);
129 /* ------------------------------------------------------------ */
130 /** Clear the buffer to be empty in flush mode.
131 * The position and limit are set to 0;
132 * @param buffer The buffer to clear.
134 public static void clear(ByteBuffer buffer)
143 /* ------------------------------------------------------------ */
144 /** Clear the buffer to be empty in fill mode.
145 * The position is set to 0 and the limit is set to the capacity.
146 * @param buffer The buffer to clear.
148 public static void clearToFill(ByteBuffer buffer)
153 buffer.limit(buffer.capacity());
157 /* ------------------------------------------------------------ */
158 /** Flip the buffer to fill mode.
159 * The position is set to the first unused position in the buffer
160 * (the old limit) and the limit is set to the capacity.
161 * If the buffer is empty, then this call is effectively {@link #clearToFill(ByteBuffer)}.
162 * If there is no unused space to fill, a {@link ByteBuffer#compact()} is done to attempt
165 * This method is used as a replacement to {@link ByteBuffer#compact()}.
167 * @param buffer The buffer to flip
168 * @return The position of the valid data before the flipped position. This value should be
169 * passed to a subsequent call to {@link #flipToFlush(ByteBuffer, int)}
171 public static int flipToFill(ByteBuffer buffer)
173 int position = buffer.position();
174 int limit = buffer.limit();
175 if (position == limit)
178 buffer.limit(buffer.capacity());
182 int capacity = buffer.capacity();
183 if (limit == capacity)
189 buffer.position(limit);
190 buffer.limit(capacity);
195 /* ------------------------------------------------------------ */
196 /** Flip the buffer to Flush mode.
197 * The limit is set to the first unused byte(the old position) and
198 * the position is set to the passed position.
200 * This method is used as a replacement of {@link Buffer#flip()}.
201 * @param buffer the buffer to be flipped
202 * @param position The position of valid data to flip to. This should
203 * be the return value of the previous call to {@link #flipToFill(ByteBuffer)}
205 public static void flipToFlush(ByteBuffer buffer, int position)
207 buffer.limit(buffer.position());
208 buffer.position(position);
212 /* ------------------------------------------------------------ */
213 /** Convert a ByteBuffer to a byte array.
214 * @param buffer The buffer to convert in flush mode. The buffer is not altered.
215 * @return An array of bytes duplicated from the buffer.
217 public static byte[] toArray(ByteBuffer buffer)
219 if (buffer.hasArray())
221 byte[] array = buffer.array();
222 int from=buffer.arrayOffset() + buffer.position();
223 return Arrays.copyOfRange(array,from,from+buffer.remaining());
227 byte[] to = new byte[buffer.remaining()];
228 buffer.slice().get(to);
233 /* ------------------------------------------------------------ */
234 /** Check for an empty or null buffer.
235 * @param buf the buffer to check
236 * @return true if the buffer is null or empty.
238 public static boolean isEmpty(ByteBuffer buf)
240 return buf == null || buf.remaining() == 0;
243 /* ------------------------------------------------------------ */
244 /** Check for a non null and non empty buffer.
245 * @param buf the buffer to check
246 * @return true if the buffer is not null and not empty.
248 public static boolean hasContent(ByteBuffer buf)
250 return buf != null && buf.remaining() > 0;
253 /* ------------------------------------------------------------ */
254 /** Check for a non null and full buffer.
255 * @param buf the buffer to check
256 * @return true if the buffer is not null and the limit equals the capacity.
258 public static boolean isFull(ByteBuffer buf)
260 return buf != null && buf.limit() == buf.capacity();
263 /* ------------------------------------------------------------ */
264 /** Get remaining from null checked buffer
265 * @param buffer The buffer to get the remaining from, in flush mode.
266 * @return 0 if the buffer is null, else the bytes remaining in the buffer.
268 public static int length(ByteBuffer buffer)
270 return buffer == null ? 0 : buffer.remaining();
273 /* ------------------------------------------------------------ */
274 /** Get the space from the limit to the capacity
275 * @param buffer the buffer to get the space from
278 public static int space(ByteBuffer buffer)
282 return buffer.capacity() - buffer.limit();
285 /* ------------------------------------------------------------ */
286 /** Compact the buffer
287 * @param buffer the buffer to compact
288 * @return true if the compact made a full buffer have space
290 public static boolean compact(ByteBuffer buffer)
292 if (buffer.position()==0)
294 boolean full = buffer.limit() == buffer.capacity();
295 buffer.compact().flip();
296 return full && buffer.limit() < buffer.capacity();
299 /* ------------------------------------------------------------ */
301 * Put data from one buffer into another, avoiding over/under flows
302 * @param from Buffer to take bytes from in flush mode
303 * @param to Buffer to put bytes to in fill mode.
304 * @return number of bytes moved
306 public static int put(ByteBuffer from, ByteBuffer to)
309 int remaining = from.remaining();
312 if (remaining <= to.remaining())
319 else if (from.hasArray())
321 put = to.remaining();
322 to.put(from.array(), from.arrayOffset() + from.position(), put);
323 from.position(from.position() + put);
327 put = to.remaining();
328 ByteBuffer slice = from.slice();
331 from.position(from.position() + put);
340 /* ------------------------------------------------------------ */
342 * Put data from one buffer into another, avoiding over/under flows
343 * @param from Buffer to take bytes from in flush mode
344 * @param to Buffer to put bytes to in flush mode. The buffer is flipToFill before the put and flipToFlush after.
345 * @return number of bytes moved
346 * @deprecated use {@link #append(ByteBuffer, ByteBuffer)}
348 public static int flipPutFlip(ByteBuffer from, ByteBuffer to)
350 return append(to,from);
353 /* ------------------------------------------------------------ */
354 /** Append bytes to a buffer.
355 * @param to Buffer is flush mode
356 * @param b bytes to append
357 * @param off offset into byte
358 * @param len length to append
359 * @throws BufferOverflowException
361 public static void append(ByteBuffer to, byte[] b, int off, int len) throws BufferOverflowException
363 int pos = flipToFill(to);
370 flipToFlush(to, pos);
374 /* ------------------------------------------------------------ */
375 /** Appends a byte to a buffer
376 * @param to Buffer is flush mode
377 * @param b byte to append
379 public static void append(ByteBuffer to, byte b)
381 int pos = flipToFill(to);
388 flipToFlush(to, pos);
392 /* ------------------------------------------------------------ */
393 /** Appends a byte to a buffer
394 * @param to Buffer is flush mode
395 * @param b bytes to append
397 public static int append(ByteBuffer to, ByteBuffer b)
399 int pos = flipToFill(to);
406 flipToFlush(to, pos);
410 /* ------------------------------------------------------------ */
412 * Like append, but does not throw {@link BufferOverflowException}
413 * @param to Buffer is flush mode
414 * @param b bytes to fill
415 * @param off offset into byte
416 * @param len length to fill
418 public static int fill(ByteBuffer to, byte[] b, int off, int len)
420 int pos = flipToFill(to);
423 int remaining = to.remaining();
424 int take = remaining < len ? remaining : len;
425 to.put(b, off, take);
430 flipToFlush(to, pos);
435 /* ------------------------------------------------------------ */
436 public static void readFrom(File file, ByteBuffer buffer) throws IOException
438 try(RandomAccessFile raf = new RandomAccessFile(file,"r"))
440 FileChannel channel = raf.getChannel();
441 long needed=raf.length();
443 while (needed>0 && buffer.hasRemaining())
444 needed=needed-channel.read(buffer);
448 /* ------------------------------------------------------------ */
449 public static void readFrom(InputStream is, int needed, ByteBuffer buffer) throws IOException
451 ByteBuffer tmp = allocate(8192);
453 while (needed > 0 && buffer.hasRemaining())
455 int l = is.read(tmp.array(), 0, 8192);
464 /* ------------------------------------------------------------ */
465 public static void writeTo(ByteBuffer buffer, OutputStream out) throws IOException
467 if (buffer.hasArray())
468 out.write(buffer.array(), buffer.arrayOffset() + buffer.position(), buffer.remaining());
471 byte[] bytes = new byte[TEMP_BUFFER_SIZE];
472 while(buffer.hasRemaining()){
473 int byteCountToWrite = Math.min(buffer.remaining(), TEMP_BUFFER_SIZE);
474 buffer.get(bytes, 0, byteCountToWrite);
475 out.write(bytes,0 , byteCountToWrite);
480 /* ------------------------------------------------------------ */
481 /** Convert the buffer to an ISO-8859-1 String
482 * @param buffer The buffer to convert in flush mode. The buffer is unchanged
483 * @return The buffer as a string.
485 public static String toString(ByteBuffer buffer)
487 return toString(buffer, StandardCharsets.ISO_8859_1);
490 /* ------------------------------------------------------------ */
491 /** Convert the buffer to an UTF-8 String
492 * @param buffer The buffer to convert in flush mode. The buffer is unchanged
493 * @return The buffer as a string.
495 public static String toUTF8String(ByteBuffer buffer)
497 return toString(buffer, StandardCharsets.UTF_8);
500 /* ------------------------------------------------------------ */
501 /** Convert the buffer to an ISO-8859-1 String
502 * @param buffer The buffer to convert in flush mode. The buffer is unchanged
503 * @param charset The {@link Charset} to use to convert the bytes
504 * @return The buffer as a string.
506 public static String toString(ByteBuffer buffer, Charset charset)
510 byte[] array = buffer.hasArray() ? buffer.array() : null;
513 byte[] to = new byte[buffer.remaining()];
514 buffer.slice().get(to);
515 return new String(to, 0, to.length, charset);
517 return new String(array, buffer.arrayOffset() + buffer.position(), buffer.remaining(), charset);
520 /* ------------------------------------------------------------ */
521 /** Convert a partial buffer to an ISO-8859-1 String
522 * @param buffer The buffer to convert in flush mode. The buffer is unchanged
523 * @param charset The {@link Charset} to use to convert the bytes
524 * @return The buffer as a string.
526 public static String toString(ByteBuffer buffer, int position, int length, Charset charset)
530 byte[] array = buffer.hasArray() ? buffer.array() : null;
533 ByteBuffer ro = buffer.asReadOnlyBuffer();
534 ro.position(position);
535 ro.limit(position + length);
536 byte[] to = new byte[length];
538 return new String(to, 0, to.length, charset);
540 return new String(array, buffer.arrayOffset() + position, length, charset);
543 /* ------------------------------------------------------------ */
545 * Convert buffer to an integer. Parses up to the first non-numeric character. If no number is found an IllegalArgumentException is thrown
548 * A buffer containing an integer in flush mode. The position is not changed.
551 public static int toInt(ByteBuffer buffer)
554 boolean started = false;
555 boolean minus = false;
557 for (int i = buffer.position(); i < buffer.limit(); i++)
559 byte b = buffer.get(i);
565 else if (b >= '0' && b <= '9')
567 val = val * 10 + (b - '0');
570 else if (b == MINUS && !started)
579 return minus ? (-val) : val;
580 throw new NumberFormatException(toString(buffer));
583 /* ------------------------------------------------------------ */
585 * Convert buffer to an integer. Parses up to the first non-numeric character. If no number is found an IllegalArgumentException is thrown
588 * A buffer containing an integer in flush mode. The position is updated.
591 public static int takeInt(ByteBuffer buffer)
594 boolean started = false;
595 boolean minus = false;
597 for (i = buffer.position(); i < buffer.limit(); i++)
599 byte b = buffer.get(i);
605 else if (b >= '0' && b <= '9')
607 val = val * 10 + (b - '0');
610 else if (b == MINUS && !started)
621 return minus ? (-val) : val;
623 throw new NumberFormatException(toString(buffer));
627 * Convert buffer to an long. Parses up to the first non-numeric character. If no number is found an IllegalArgumentException is thrown
630 * A buffer containing an integer in flush mode. The position is not changed.
633 public static long toLong(ByteBuffer buffer)
636 boolean started = false;
637 boolean minus = false;
639 for (int i = buffer.position(); i < buffer.limit(); i++)
641 byte b = buffer.get(i);
647 else if (b >= '0' && b <= '9')
649 val = val * 10L + (b - '0');
652 else if (b == MINUS && !started)
661 return minus ? (-val) : val;
662 throw new NumberFormatException(toString(buffer));
665 public static void putHexInt(ByteBuffer buffer, int n)
669 buffer.put((byte)'-');
671 if (n == Integer.MIN_VALUE)
673 buffer.put((byte)(0x7f & '8'));
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 buffer.put((byte)(0x7f & '0'));
689 buffer.put(DIGIT[n]);
693 boolean started = false;
694 // This assumes constant time int arithmatic
695 for (int hexDivisor : hexDivisors)
700 buffer.put((byte)'0');
705 int d = n / hexDivisor;
706 buffer.put(DIGIT[d]);
707 n = n - d * hexDivisor;
712 /* ------------------------------------------------------------ */
713 public static void putDecInt(ByteBuffer buffer, int n)
717 buffer.put((byte)'-');
719 if (n == Integer.MIN_VALUE)
721 buffer.put((byte)'2');
730 buffer.put(DIGIT[n]);
734 boolean started = false;
735 // This assumes constant time int arithmatic
736 for (int decDivisor : decDivisors)
741 buffer.put((byte)'0');
746 int d = n / decDivisor;
747 buffer.put(DIGIT[d]);
748 n = n - d * decDivisor;
753 public static void putDecLong(ByteBuffer buffer, long n)
757 buffer.put((byte)'-');
759 if (n == Long.MIN_VALUE)
761 buffer.put((byte)'9');
762 n = 223372036854775808L;
770 buffer.put(DIGIT[(int)n]);
774 boolean started = false;
775 // This assumes constant time int arithmatic
776 for (long aDecDivisorsL : decDivisorsL)
778 if (n < aDecDivisorsL)
781 buffer.put((byte)'0');
786 long d = n / aDecDivisorsL;
787 buffer.put(DIGIT[(int)d]);
788 n = n - d * aDecDivisorsL;
793 public static ByteBuffer toBuffer(int value)
795 ByteBuffer buf = ByteBuffer.allocate(32);
796 putDecInt(buf, value);
800 public static ByteBuffer toBuffer(long value)
802 ByteBuffer buf = ByteBuffer.allocate(32);
803 putDecLong(buf, value);
807 public static ByteBuffer toBuffer(String s)
809 return ByteBuffer.wrap(s.getBytes(StandardCharsets.ISO_8859_1));
812 public static ByteBuffer toDirectBuffer(String s)
814 byte[] bytes = s.getBytes(StandardCharsets.ISO_8859_1);
815 ByteBuffer buf = ByteBuffer.allocateDirect(bytes.length);
821 public static ByteBuffer toBuffer(String s, Charset charset)
823 return ByteBuffer.wrap(s.getBytes(charset));
826 public static ByteBuffer toDirectBuffer(String s, Charset charset)
828 byte[] bytes = s.getBytes(charset);
829 ByteBuffer buf = ByteBuffer.allocateDirect(bytes.length);
836 * Create a new ByteBuffer using provided byte array.
839 * the byte array to back buffer with.
840 * @return ByteBuffer with provided byte array, in flush mode
842 public static ByteBuffer toBuffer(byte array[])
844 return ByteBuffer.wrap(array);
848 * Create a new ByteBuffer using the provided byte array.
851 * the byte array to use.
853 * the offset within the byte array to use from
855 * the length in bytes of the array to use
856 * @return ByteBuffer with provided byte array, in flush mode
858 public static ByteBuffer toBuffer(byte array[], int offset, int length)
860 return ByteBuffer.wrap(array, offset, length);
863 public static ByteBuffer toMappedBuffer(File file) throws IOException
865 try (RandomAccessFile raf = new RandomAccessFile(file, "r"))
867 return raf.getChannel().map(MapMode.READ_ONLY, 0, raf.length());
871 public static ByteBuffer toBuffer(Resource resource,boolean direct) throws IOException
873 int len=(int)resource.length();
875 throw new IllegalArgumentException("invalid resource: "+String.valueOf(resource)+" len="+len);
877 ByteBuffer buffer = direct?BufferUtil.allocateDirect(len):BufferUtil.allocate(len);
879 int pos=BufferUtil.flipToFill(buffer);
880 if (resource.getFile()!=null)
881 BufferUtil.readFrom(resource.getFile(),buffer);
884 try (InputStream is = resource.getInputStream();)
886 BufferUtil.readFrom(is,len,buffer);
889 BufferUtil.flipToFlush(buffer,pos);
894 public static String toSummaryString(ByteBuffer buffer)
898 StringBuilder buf = new StringBuilder();
900 buf.append(buffer.position());
902 buf.append(buffer.limit());
904 buf.append(buffer.capacity());
906 buf.append(buffer.remaining());
908 return buf.toString();
911 public static String toDetailString(ByteBuffer[] buffer)
913 StringBuilder builder = new StringBuilder();
915 for (int i = 0; i < buffer.length; i++)
917 if (i > 0) builder.append(',');
918 builder.append(toDetailString(buffer[i]));
921 return builder.toString();
924 public static String toDetailString(ByteBuffer buffer)
929 StringBuilder buf = new StringBuilder();
930 buf.append(buffer.getClass().getSimpleName());
932 if (buffer.hasArray())
933 buf.append(Integer.toHexString(((Object)buffer.array()).hashCode()));
935 buf.append(Integer.toHexString(buf.hashCode()));
937 buf.append(buffer.position());
939 buf.append(buffer.limit());
941 buf.append(buffer.capacity());
943 buf.append(buffer.remaining());
946 for (int i = 0; i < buffer.position(); i++)
948 char c = (char)buffer.get(i);
949 if (c >= ' ' && c <= 127)
951 else if (c == '\r' || c == '\n')
954 buf.append('\ufffd');
955 if (i == 16 && buffer.position() > 32)
958 i = buffer.position() - 16;
962 for (int i = buffer.position(); i < buffer.limit(); i++)
964 char c = (char)buffer.get(i);
965 if (c >= ' ' && c <= 127)
967 else if (c == '\r' || c == '\n')
970 buf.append('\ufffd');
971 if (i == buffer.position() + 16 && buffer.limit() > buffer.position() + 32)
974 i = buffer.limit() - 16;
978 int limit = buffer.limit();
979 buffer.limit(buffer.capacity());
980 for (int i = limit; i < buffer.capacity(); i++)
982 char c = (char)buffer.get(i);
983 if (c >= ' ' && c <= 127)
985 else if (c == '\r' || c == '\n')
988 buf.append('\ufffd');
989 if (i == limit + 16 && buffer.capacity() > limit + 32)
992 i = buffer.capacity() - 16;
998 return buf.toString();
1002 private final static int[] decDivisors =
1003 {1000000000, 100000000, 10000000, 1000000, 100000, 10000, 1000, 100, 10, 1};
1005 private final static int[] hexDivisors =
1006 {0x10000000, 0x1000000, 0x100000, 0x10000, 0x1000, 0x100, 0x10, 0x1};
1008 private final static long[] decDivisorsL =
1009 {1000000000000000000L, 100000000000000000L, 10000000000000000L, 1000000000000000L, 100000000000000L, 10000000000000L, 1000000000000L, 100000000000L,
1010 10000000000L, 1000000000L, 100000000L, 10000000L, 1000000L, 100000L, 10000L, 1000L, 100L, 10L, 1L};
1012 public static void putCRLF(ByteBuffer buffer)
1014 buffer.put((byte)13);
1015 buffer.put((byte)10);
1018 public static boolean isPrefix(ByteBuffer prefix, ByteBuffer buffer)
1020 if (prefix.remaining() > buffer.remaining())
1022 int bi = buffer.position();
1023 for (int i = prefix.position(); i < prefix.limit(); i++)
1024 if (prefix.get(i) != buffer.get(bi++))
1029 public static ByteBuffer ensureCapacity(ByteBuffer buffer, int capacity)
1032 return allocate(capacity);
1034 if (buffer.capacity()>=capacity)
1037 if (buffer.hasArray())
1038 return ByteBuffer.wrap(Arrays.copyOfRange(buffer.array(), buffer.arrayOffset(), buffer.arrayOffset()+capacity),buffer.position(),buffer.remaining());
1040 throw new UnsupportedOperationException();