View Javadoc

1   /*
2    * Copyright 2012 The Netty Project
3    *
4    * The Netty Project licenses this file to you under the Apache License,
5    * version 2.0 (the "License"); you may not use this file except in compliance
6    * with the License. You may obtain a copy of the License at:
7    *
8    *   http://www.apache.org/licenses/LICENSE-2.0
9    *
10   * Unless required by applicable law or agreed to in writing, software
11   * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
12   * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
13   * License for the specific language governing permissions and limitations
14   * under the License.
15   */
16  package io.netty.buffer;
17  
18  import io.netty.util.internal.PlatformDependent;
19  
20  import java.nio.ByteBuffer;
21  import java.nio.ByteOrder;
22  import java.nio.CharBuffer;
23  import java.nio.charset.Charset;
24  import java.util.ArrayList;
25  import java.util.List;
26  
27  
28  /**
29   * Creates a new {@link ByteBuf} by allocating new space or by wrapping
30   * or copying existing byte arrays, byte buffers and a string.
31   *
32   * <h3>Use static import</h3>
33   * This classes is intended to be used with Java 5 static import statement:
34   *
35   * <pre>
36   * import static io.netty.buffer.{@link Unpooled}.*;
37   *
38   * {@link ByteBuf} heapBuffer    = buffer(128);
39   * {@link ByteBuf} directBuffer  = directBuffer(256);
40   * {@link ByteBuf} wrappedBuffer = wrappedBuffer(new byte[128], new byte[256]);
41   * {@link ByteBuf} copiedBuffer  = copiedBuffer({@link ByteBuffer}.allocate(128));
42   * </pre>
43   *
44   * <h3>Allocating a new buffer</h3>
45   *
46   * Three buffer types are provided out of the box.
47   *
48   * <ul>
49   * <li>{@link #buffer(int)} allocates a new fixed-capacity heap buffer.</li>
50   * <li>{@link #directBuffer(int)} allocates a new fixed-capacity direct buffer.</li>
51   * </ul>
52   *
53   * <h3>Creating a wrapped buffer</h3>
54   *
55   * Wrapped buffer is a buffer which is a view of one or more existing
56   * byte arrays and byte buffers.  Any changes in the content of the original
57   * array or buffer will be visible in the wrapped buffer.  Various wrapper
58   * methods are provided and their name is all {@code wrappedBuffer()}.
59   * You might want to take a look at the methods that accept varargs closely if
60   * you want to create a buffer which is composed of more than one array to
61   * reduce the number of memory copy.
62   *
63   * <h3>Creating a copied buffer</h3>
64   *
65   * Copied buffer is a deep copy of one or more existing byte arrays, byte
66   * buffers or a string.  Unlike a wrapped buffer, there's no shared data
67   * between the original data and the copied buffer.  Various copy methods are
68   * provided and their name is all {@code copiedBuffer()}.  It is also convenient
69   * to use this operation to merge multiple buffers into one buffer.
70   */
71  public final class Unpooled {
72  
73      private static final ByteBufAllocator ALLOC = UnpooledByteBufAllocator.DEFAULT;
74  
75      /**
76       * Big endian byte order.
77       */
78      public static final ByteOrder BIG_ENDIAN = ByteOrder.BIG_ENDIAN;
79  
80      /**
81       * Little endian byte order.
82       */
83      public static final ByteOrder LITTLE_ENDIAN = ByteOrder.LITTLE_ENDIAN;
84  
85      /**
86       * A buffer whose capacity is {@code 0}.
87       */
88      public static final ByteBuf EMPTY_BUFFER = ALLOC.buffer(0, 0);
89  
90      static {
91          assert EMPTY_BUFFER instanceof EmptyByteBuf: "EMPTY_BUFFER must be an EmptyByteBuf.";
92      }
93  
94      /**
95       * Creates a new big-endian Java heap buffer with reasonably small initial capacity, which
96       * expands its capacity boundlessly on demand.
97       */
98      public static ByteBuf buffer() {
99          return ALLOC.heapBuffer();
100     }
101 
102     /**
103      * Creates a new big-endian direct buffer with reasonably small initial capacity, which
104      * expands its capacity boundlessly on demand.
105      */
106     public static ByteBuf directBuffer() {
107         return ALLOC.directBuffer();
108     }
109 
110     /**
111      * Creates a new big-endian Java heap buffer with the specified {@code capacity}, which
112      * expands its capacity boundlessly on demand.  The new buffer's {@code readerIndex} and
113      * {@code writerIndex} are {@code 0}.
114      */
115     public static ByteBuf buffer(int initialCapacity) {
116         return ALLOC.heapBuffer(initialCapacity);
117     }
118 
119     /**
120      * Creates a new big-endian direct buffer with the specified {@code capacity}, which
121      * expands its capacity boundlessly on demand.  The new buffer's {@code readerIndex} and
122      * {@code writerIndex} are {@code 0}.
123      */
124     public static ByteBuf directBuffer(int initialCapacity) {
125         return ALLOC.directBuffer(initialCapacity);
126     }
127 
128     /**
129      * Creates a new big-endian Java heap buffer with the specified
130      * {@code initialCapacity}, that may grow up to {@code maxCapacity}
131      * The new buffer's {@code readerIndex} and {@code writerIndex} are
132      * {@code 0}.
133      */
134     public static ByteBuf buffer(int initialCapacity, int maxCapacity) {
135         return ALLOC.heapBuffer(initialCapacity, maxCapacity);
136     }
137 
138     /**
139      * Creates a new big-endian direct buffer with the specified
140      * {@code initialCapacity}, that may grow up to {@code maxCapacity}.
141      * The new buffer's {@code readerIndex} and {@code writerIndex} are
142      * {@code 0}.
143      */
144     public static ByteBuf directBuffer(int initialCapacity, int maxCapacity) {
145         return ALLOC.directBuffer(initialCapacity, maxCapacity);
146     }
147 
148     /**
149      * Creates a new big-endian buffer which wraps the specified {@code array}.
150      * A modification on the specified array's content will be visible to the
151      * returned buffer.
152      */
153     public static ByteBuf wrappedBuffer(byte[] array) {
154         if (array.length == 0) {
155             return EMPTY_BUFFER;
156         }
157         return new UnpooledHeapByteBuf(ALLOC, array, array.length);
158     }
159 
160     /**
161      * Creates a new big-endian buffer which wraps the sub-region of the
162      * specified {@code array}.  A modification on the specified array's
163      * content will be visible to the returned buffer.
164      */
165     public static ByteBuf wrappedBuffer(byte[] array, int offset, int length) {
166         if (length == 0) {
167             return EMPTY_BUFFER;
168         }
169 
170         if (offset == 0 && length == array.length) {
171             return wrappedBuffer(array);
172         }
173 
174         return wrappedBuffer(array).slice(offset, length);
175     }
176 
177     /**
178      * Creates a new buffer which wraps the specified NIO buffer's current
179      * slice.  A modification on the specified buffer's content will be
180      * visible to the returned buffer.
181      */
182     public static ByteBuf wrappedBuffer(ByteBuffer buffer) {
183         if (!buffer.hasRemaining()) {
184             return EMPTY_BUFFER;
185         }
186         if (!buffer.isDirect() && buffer.hasArray()) {
187             return wrappedBuffer(
188                     buffer.array(),
189                     buffer.arrayOffset() + buffer.position(),
190                     buffer.remaining()).order(buffer.order());
191         } else if (PlatformDependent.hasUnsafe()) {
192             if (buffer.isReadOnly()) {
193                 if (buffer.isDirect()) {
194                     return new ReadOnlyUnsafeDirectByteBuf(ALLOC, buffer);
195                 } else {
196                     return new ReadOnlyByteBufferBuf(ALLOC, buffer);
197                 }
198             } else {
199                 return new UnpooledUnsafeDirectByteBuf(ALLOC, buffer, buffer.remaining());
200             }
201         } else {
202             if (buffer.isReadOnly()) {
203                 return new ReadOnlyByteBufferBuf(ALLOC, buffer);
204             }  else {
205                 return new UnpooledDirectByteBuf(ALLOC, buffer, buffer.remaining());
206             }
207         }
208     }
209 
210     /**
211      * Creates a new buffer which wraps the specified memory address. If {@code doFree} is true the
212      * memoryAddress will automatically be freed once the reference count of the {@link ByteBuf} reaches {@code 0}.
213      */
214     public static ByteBuf wrappedBuffer(long memoryAddress, int size, boolean doFree) {
215         return new WrappedUnpooledUnsafeDirectByteBuf(ALLOC, memoryAddress, size, doFree);
216     }
217 
218     /**
219      * Creates a new buffer which wraps the specified buffer's readable bytes.
220      * A modification on the specified buffer's content will be visible to the
221      * returned buffer.
222      * @param buffer The buffer to wrap. Reference count ownership of this variable is transfered to this method.
223      * @return The readable portion of the {@code buffer}, or an empty buffer if there is no readable portion.
224      * The caller is responsible for releasing this buffer.
225      */
226     public static ByteBuf wrappedBuffer(ByteBuf buffer) {
227         if (buffer.isReadable()) {
228             return buffer.slice();
229         } else {
230             buffer.release();
231             return EMPTY_BUFFER;
232         }
233     }
234 
235     /**
236      * Creates a new big-endian composite buffer which wraps the specified
237      * arrays without copying them.  A modification on the specified arrays'
238      * content will be visible to the returned buffer.
239      */
240     public static ByteBuf wrappedBuffer(byte[]... arrays) {
241         return wrappedBuffer(AbstractByteBufAllocator.DEFAULT_MAX_COMPONENTS, arrays);
242     }
243 
244     /**
245      * Creates a new big-endian composite buffer which wraps the readable bytes of the
246      * specified buffers without copying them.  A modification on the content
247      * of the specified buffers will be visible to the returned buffer.
248      * @param buffers The buffers to wrap. Reference count ownership of all variables is transfered to this method.
249      * @return The readable portion of the {@code buffers}. The caller is responsible for releasing this buffer.
250      */
251     public static ByteBuf wrappedBuffer(ByteBuf... buffers) {
252         return wrappedBuffer(AbstractByteBufAllocator.DEFAULT_MAX_COMPONENTS, buffers);
253     }
254 
255     /**
256      * Creates a new big-endian composite buffer which wraps the slices of the specified
257      * NIO buffers without copying them.  A modification on the content of the
258      * specified buffers will be visible to the returned buffer.
259      */
260     public static ByteBuf wrappedBuffer(ByteBuffer... buffers) {
261         return wrappedBuffer(AbstractByteBufAllocator.DEFAULT_MAX_COMPONENTS, buffers);
262     }
263 
264     /**
265      * Creates a new big-endian composite buffer which wraps the specified
266      * arrays without copying them.  A modification on the specified arrays'
267      * content will be visible to the returned buffer.
268      */
269     public static ByteBuf wrappedBuffer(int maxNumComponents, byte[]... arrays) {
270         switch (arrays.length) {
271         case 0:
272             break;
273         case 1:
274             if (arrays[0].length != 0) {
275                 return wrappedBuffer(arrays[0]);
276             }
277             break;
278         default:
279             // Get the list of the component, while guessing the byte order.
280             final List<ByteBuf> components = new ArrayList<ByteBuf>(arrays.length);
281             for (byte[] a: arrays) {
282                 if (a == null) {
283                     break;
284                 }
285                 if (a.length > 0) {
286                     components.add(wrappedBuffer(a));
287                 }
288             }
289 
290             if (!components.isEmpty()) {
291                 return new CompositeByteBuf(ALLOC, false, maxNumComponents, components);
292             }
293         }
294 
295         return EMPTY_BUFFER;
296     }
297 
298     /**
299      * Creates a new big-endian composite buffer which wraps the readable bytes of the
300      * specified buffers without copying them.  A modification on the content
301      * of the specified buffers will be visible to the returned buffer.
302      * @param maxNumComponents Advisement as to how many independent buffers are allowed to exist before
303      * consolidation occurs.
304      * @param buffers The buffers to wrap. Reference count ownership of all variables is transfered to this method.
305      * @return The readable portion of the {@code buffers}. The caller is responsible for releasing this buffer.
306      */
307     public static ByteBuf wrappedBuffer(int maxNumComponents, ByteBuf... buffers) {
308         switch (buffers.length) {
309         case 0:
310             break;
311         case 1:
312             ByteBuf buffer = buffers[0];
313             if (buffer.isReadable()) {
314                 return wrappedBuffer(buffer.order(BIG_ENDIAN));
315             } else {
316                 buffer.release();
317             }
318             break;
319         default:
320             for (int i = 0; i < buffers.length; i++) {
321                 ByteBuf buf = buffers[i];
322                 if (buf.isReadable()) {
323                     return new CompositeByteBuf(ALLOC, false, maxNumComponents, buffers, i, buffers.length);
324                 }
325                 buf.release();
326             }
327             break;
328         }
329         return EMPTY_BUFFER;
330     }
331 
332     /**
333      * Creates a new big-endian composite buffer which wraps the slices of the specified
334      * NIO buffers without copying them.  A modification on the content of the
335      * specified buffers will be visible to the returned buffer.
336      */
337     public static ByteBuf wrappedBuffer(int maxNumComponents, ByteBuffer... buffers) {
338         switch (buffers.length) {
339         case 0:
340             break;
341         case 1:
342             if (buffers[0].hasRemaining()) {
343                 return wrappedBuffer(buffers[0].order(BIG_ENDIAN));
344             }
345             break;
346         default:
347             // Get the list of the component, while guessing the byte order.
348             final List<ByteBuf> components = new ArrayList<ByteBuf>(buffers.length);
349             for (ByteBuffer b: buffers) {
350                 if (b == null) {
351                     break;
352                 }
353                 if (b.remaining() > 0) {
354                     components.add(wrappedBuffer(b.order(BIG_ENDIAN)));
355                 }
356             }
357 
358             if (!components.isEmpty()) {
359                 return new CompositeByteBuf(ALLOC, false, maxNumComponents, components);
360             }
361         }
362 
363         return EMPTY_BUFFER;
364     }
365 
366     /**
367      * Returns a new big-endian composite buffer with no components.
368      */
369     public static CompositeByteBuf compositeBuffer() {
370         return compositeBuffer(AbstractByteBufAllocator.DEFAULT_MAX_COMPONENTS);
371     }
372 
373     /**
374      * Returns a new big-endian composite buffer with no components.
375      */
376     public static CompositeByteBuf compositeBuffer(int maxNumComponents) {
377         return new CompositeByteBuf(ALLOC, false, maxNumComponents);
378     }
379 
380     /**
381      * Creates a new big-endian buffer whose content is a copy of the
382      * specified {@code array}.  The new buffer's {@code readerIndex} and
383      * {@code writerIndex} are {@code 0} and {@code array.length} respectively.
384      */
385     public static ByteBuf copiedBuffer(byte[] array) {
386         if (array.length == 0) {
387             return EMPTY_BUFFER;
388         }
389         return wrappedBuffer(array.clone());
390     }
391 
392     /**
393      * Creates a new big-endian buffer whose content is a copy of the
394      * specified {@code array}'s sub-region.  The new buffer's
395      * {@code readerIndex} and {@code writerIndex} are {@code 0} and
396      * the specified {@code length} respectively.
397      */
398     public static ByteBuf copiedBuffer(byte[] array, int offset, int length) {
399         if (length == 0) {
400             return EMPTY_BUFFER;
401         }
402         byte[] copy = new byte[length];
403         System.arraycopy(array, offset, copy, 0, length);
404         return wrappedBuffer(copy);
405     }
406 
407     /**
408      * Creates a new buffer whose content is a copy of the specified
409      * {@code buffer}'s current slice.  The new buffer's {@code readerIndex}
410      * and {@code writerIndex} are {@code 0} and {@code buffer.remaining}
411      * respectively.
412      */
413     public static ByteBuf copiedBuffer(ByteBuffer buffer) {
414         int length = buffer.remaining();
415         if (length == 0) {
416             return EMPTY_BUFFER;
417         }
418         byte[] copy = new byte[length];
419         // Duplicate the buffer so we not adjust the position during our get operation.
420         // See https://github.com/netty/netty/issues/3896
421         ByteBuffer duplicate = buffer.duplicate();
422         duplicate.get(copy);
423         return wrappedBuffer(copy).order(duplicate.order());
424     }
425 
426     /**
427      * Creates a new buffer whose content is a copy of the specified
428      * {@code buffer}'s readable bytes.  The new buffer's {@code readerIndex}
429      * and {@code writerIndex} are {@code 0} and {@code buffer.readableBytes}
430      * respectively.
431      */
432     public static ByteBuf copiedBuffer(ByteBuf buffer) {
433         int readable = buffer.readableBytes();
434         if (readable > 0) {
435             ByteBuf copy = buffer(readable);
436             copy.writeBytes(buffer, buffer.readerIndex(), readable);
437             return copy;
438         } else {
439             return EMPTY_BUFFER;
440         }
441     }
442 
443     /**
444      * Creates a new big-endian buffer whose content is a merged copy of
445      * the specified {@code arrays}.  The new buffer's {@code readerIndex}
446      * and {@code writerIndex} are {@code 0} and the sum of all arrays'
447      * {@code length} respectively.
448      */
449     public static ByteBuf copiedBuffer(byte[]... arrays) {
450         switch (arrays.length) {
451         case 0:
452             return EMPTY_BUFFER;
453         case 1:
454             if (arrays[0].length == 0) {
455                 return EMPTY_BUFFER;
456             } else {
457                 return copiedBuffer(arrays[0]);
458             }
459         }
460 
461         // Merge the specified arrays into one array.
462         int length = 0;
463         for (byte[] a: arrays) {
464             if (Integer.MAX_VALUE - length < a.length) {
465                 throw new IllegalArgumentException(
466                         "The total length of the specified arrays is too big.");
467             }
468             length += a.length;
469         }
470 
471         if (length == 0) {
472             return EMPTY_BUFFER;
473         }
474 
475         byte[] mergedArray = new byte[length];
476         for (int i = 0, j = 0; i < arrays.length; i ++) {
477             byte[] a = arrays[i];
478             System.arraycopy(a, 0, mergedArray, j, a.length);
479             j += a.length;
480         }
481 
482         return wrappedBuffer(mergedArray);
483     }
484 
485     /**
486      * Creates a new buffer whose content is a merged copy of the specified
487      * {@code buffers}' readable bytes.  The new buffer's {@code readerIndex}
488      * and {@code writerIndex} are {@code 0} and the sum of all buffers'
489      * {@code readableBytes} respectively.
490      *
491      * @throws IllegalArgumentException
492      *         if the specified buffers' endianness are different from each
493      *         other
494      */
495     public static ByteBuf copiedBuffer(ByteBuf... buffers) {
496         switch (buffers.length) {
497         case 0:
498             return EMPTY_BUFFER;
499         case 1:
500             return copiedBuffer(buffers[0]);
501         }
502 
503         // Merge the specified buffers into one buffer.
504         ByteOrder order = null;
505         int length = 0;
506         for (ByteBuf b: buffers) {
507             int bLen = b.readableBytes();
508             if (bLen <= 0) {
509                 continue;
510             }
511             if (Integer.MAX_VALUE - length < bLen) {
512                 throw new IllegalArgumentException(
513                         "The total length of the specified buffers is too big.");
514             }
515             length += bLen;
516             if (order != null) {
517                 if (!order.equals(b.order())) {
518                     throw new IllegalArgumentException("inconsistent byte order");
519                 }
520             } else {
521                 order = b.order();
522             }
523         }
524 
525         if (length == 0) {
526             return EMPTY_BUFFER;
527         }
528 
529         byte[] mergedArray = new byte[length];
530         for (int i = 0, j = 0; i < buffers.length; i ++) {
531             ByteBuf b = buffers[i];
532             int bLen = b.readableBytes();
533             b.getBytes(b.readerIndex(), mergedArray, j, bLen);
534             j += bLen;
535         }
536 
537         return wrappedBuffer(mergedArray).order(order);
538     }
539 
540     /**
541      * Creates a new buffer whose content is a merged copy of the specified
542      * {@code buffers}' slices.  The new buffer's {@code readerIndex} and
543      * {@code writerIndex} are {@code 0} and the sum of all buffers'
544      * {@code remaining} respectively.
545      *
546      * @throws IllegalArgumentException
547      *         if the specified buffers' endianness are different from each
548      *         other
549      */
550     public static ByteBuf copiedBuffer(ByteBuffer... buffers) {
551         switch (buffers.length) {
552         case 0:
553             return EMPTY_BUFFER;
554         case 1:
555             return copiedBuffer(buffers[0]);
556         }
557 
558         // Merge the specified buffers into one buffer.
559         ByteOrder order = null;
560         int length = 0;
561         for (ByteBuffer b: buffers) {
562             int bLen = b.remaining();
563             if (bLen <= 0) {
564                 continue;
565             }
566             if (Integer.MAX_VALUE - length < bLen) {
567                 throw new IllegalArgumentException(
568                         "The total length of the specified buffers is too big.");
569             }
570             length += bLen;
571             if (order != null) {
572                 if (!order.equals(b.order())) {
573                     throw new IllegalArgumentException("inconsistent byte order");
574                 }
575             } else {
576                 order = b.order();
577             }
578         }
579 
580         if (length == 0) {
581             return EMPTY_BUFFER;
582         }
583 
584         byte[] mergedArray = new byte[length];
585         for (int i = 0, j = 0; i < buffers.length; i ++) {
586             // Duplicate the buffer so we not adjust the position during our get operation.
587             // See https://github.com/netty/netty/issues/3896
588             ByteBuffer b = buffers[i].duplicate();
589             int bLen = b.remaining();
590             b.get(mergedArray, j, bLen);
591             j += bLen;
592         }
593 
594         return wrappedBuffer(mergedArray).order(order);
595     }
596 
597     /**
598      * Creates a new big-endian buffer whose content is the specified
599      * {@code string} encoded in the specified {@code charset}.
600      * The new buffer's {@code readerIndex} and {@code writerIndex} are
601      * {@code 0} and the length of the encoded string respectively.
602      */
603     public static ByteBuf copiedBuffer(CharSequence string, Charset charset) {
604         if (string == null) {
605             throw new NullPointerException("string");
606         }
607 
608         if (string instanceof CharBuffer) {
609             return copiedBuffer((CharBuffer) string, charset);
610         }
611 
612         return copiedBuffer(CharBuffer.wrap(string), charset);
613     }
614 
615     /**
616      * Creates a new big-endian buffer whose content is a subregion of
617      * the specified {@code string} encoded in the specified {@code charset}.
618      * The new buffer's {@code readerIndex} and {@code writerIndex} are
619      * {@code 0} and the length of the encoded string respectively.
620      */
621     public static ByteBuf copiedBuffer(
622             CharSequence string, int offset, int length, Charset charset) {
623         if (string == null) {
624             throw new NullPointerException("string");
625         }
626         if (length == 0) {
627             return EMPTY_BUFFER;
628         }
629 
630         if (string instanceof CharBuffer) {
631             CharBuffer buf = (CharBuffer) string;
632             if (buf.hasArray()) {
633                 return copiedBuffer(
634                         buf.array(),
635                         buf.arrayOffset() + buf.position() + offset,
636                         length, charset);
637             }
638 
639             buf = buf.slice();
640             buf.limit(length);
641             buf.position(offset);
642             return copiedBuffer(buf, charset);
643         }
644 
645         return copiedBuffer(CharBuffer.wrap(string, offset, offset + length), charset);
646     }
647 
648     /**
649      * Creates a new big-endian buffer whose content is the specified
650      * {@code array} encoded in the specified {@code charset}.
651      * The new buffer's {@code readerIndex} and {@code writerIndex} are
652      * {@code 0} and the length of the encoded string respectively.
653      */
654     public static ByteBuf copiedBuffer(char[] array, Charset charset) {
655         if (array == null) {
656             throw new NullPointerException("array");
657         }
658         return copiedBuffer(array, 0, array.length, charset);
659     }
660 
661     /**
662      * Creates a new big-endian buffer whose content is a subregion of
663      * the specified {@code array} encoded in the specified {@code charset}.
664      * The new buffer's {@code readerIndex} and {@code writerIndex} are
665      * {@code 0} and the length of the encoded string respectively.
666      */
667     public static ByteBuf copiedBuffer(char[] array, int offset, int length, Charset charset) {
668         if (array == null) {
669             throw new NullPointerException("array");
670         }
671         if (length == 0) {
672             return EMPTY_BUFFER;
673         }
674         return copiedBuffer(CharBuffer.wrap(array, offset, length), charset);
675     }
676 
677     private static ByteBuf copiedBuffer(CharBuffer buffer, Charset charset) {
678         return ByteBufUtil.encodeString0(ALLOC, true, buffer, charset);
679     }
680 
681     /**
682      * Creates a read-only buffer which disallows any modification operations
683      * on the specified {@code buffer}.  The new buffer has the same
684      * {@code readerIndex} and {@code writerIndex} with the specified
685      * {@code buffer}.
686      */
687     public static ByteBuf unmodifiableBuffer(ByteBuf buffer) {
688         ByteOrder endianness = buffer.order();
689         if (endianness == BIG_ENDIAN) {
690             return new ReadOnlyByteBuf(buffer);
691         }
692 
693         return new ReadOnlyByteBuf(buffer.order(BIG_ENDIAN)).order(LITTLE_ENDIAN);
694     }
695 
696     /**
697      * Creates a new 4-byte big-endian buffer that holds the specified 32-bit integer.
698      */
699     public static ByteBuf copyInt(int value) {
700         ByteBuf buf = buffer(4);
701         buf.writeInt(value);
702         return buf;
703     }
704 
705     /**
706      * Create a big-endian buffer that holds a sequence of the specified 32-bit integers.
707      */
708     public static ByteBuf copyInt(int... values) {
709         if (values == null || values.length == 0) {
710             return EMPTY_BUFFER;
711         }
712         ByteBuf buffer = buffer(values.length * 4);
713         for (int v: values) {
714             buffer.writeInt(v);
715         }
716         return buffer;
717     }
718 
719     /**
720      * Creates a new 2-byte big-endian buffer that holds the specified 16-bit integer.
721      */
722     public static ByteBuf copyShort(int value) {
723         ByteBuf buf = buffer(2);
724         buf.writeShort(value);
725         return buf;
726     }
727 
728     /**
729      * Create a new big-endian buffer that holds a sequence of the specified 16-bit integers.
730      */
731     public static ByteBuf copyShort(short... values) {
732         if (values == null || values.length == 0) {
733             return EMPTY_BUFFER;
734         }
735         ByteBuf buffer = buffer(values.length * 2);
736         for (int v: values) {
737             buffer.writeShort(v);
738         }
739         return buffer;
740     }
741 
742     /**
743      * Create a new big-endian buffer that holds a sequence of the specified 16-bit integers.
744      */
745     public static ByteBuf copyShort(int... values) {
746         if (values == null || values.length == 0) {
747             return EMPTY_BUFFER;
748         }
749         ByteBuf buffer = buffer(values.length * 2);
750         for (int v: values) {
751             buffer.writeShort(v);
752         }
753         return buffer;
754     }
755 
756     /**
757      * Creates a new 3-byte big-endian buffer that holds the specified 24-bit integer.
758      */
759     public static ByteBuf copyMedium(int value) {
760         ByteBuf buf = buffer(3);
761         buf.writeMedium(value);
762         return buf;
763     }
764 
765     /**
766      * Create a new big-endian buffer that holds a sequence of the specified 24-bit integers.
767      */
768     public static ByteBuf copyMedium(int... values) {
769         if (values == null || values.length == 0) {
770             return EMPTY_BUFFER;
771         }
772         ByteBuf buffer = buffer(values.length * 3);
773         for (int v: values) {
774             buffer.writeMedium(v);
775         }
776         return buffer;
777     }
778 
779     /**
780      * Creates a new 8-byte big-endian buffer that holds the specified 64-bit integer.
781      */
782     public static ByteBuf copyLong(long value) {
783         ByteBuf buf = buffer(8);
784         buf.writeLong(value);
785         return buf;
786     }
787 
788     /**
789      * Create a new big-endian buffer that holds a sequence of the specified 64-bit integers.
790      */
791     public static ByteBuf copyLong(long... values) {
792         if (values == null || values.length == 0) {
793             return EMPTY_BUFFER;
794         }
795         ByteBuf buffer = buffer(values.length * 8);
796         for (long v: values) {
797             buffer.writeLong(v);
798         }
799         return buffer;
800     }
801 
802     /**
803      * Creates a new single-byte big-endian buffer that holds the specified boolean value.
804      */
805     public static ByteBuf copyBoolean(boolean value) {
806         ByteBuf buf = buffer(1);
807         buf.writeBoolean(value);
808         return buf;
809     }
810 
811     /**
812      * Create a new big-endian buffer that holds a sequence of the specified boolean values.
813      */
814     public static ByteBuf copyBoolean(boolean... values) {
815         if (values == null || values.length == 0) {
816             return EMPTY_BUFFER;
817         }
818         ByteBuf buffer = buffer(values.length);
819         for (boolean v: values) {
820             buffer.writeBoolean(v);
821         }
822         return buffer;
823     }
824 
825     /**
826      * Creates a new 4-byte big-endian buffer that holds the specified 32-bit floating point number.
827      */
828     public static ByteBuf copyFloat(float value) {
829         ByteBuf buf = buffer(4);
830         buf.writeFloat(value);
831         return buf;
832     }
833 
834     /**
835      * Create a new big-endian buffer that holds a sequence of the specified 32-bit floating point numbers.
836      */
837     public static ByteBuf copyFloat(float... values) {
838         if (values == null || values.length == 0) {
839             return EMPTY_BUFFER;
840         }
841         ByteBuf buffer = buffer(values.length * 4);
842         for (float v: values) {
843             buffer.writeFloat(v);
844         }
845         return buffer;
846     }
847 
848     /**
849      * Creates a new 8-byte big-endian buffer that holds the specified 64-bit floating point number.
850      */
851     public static ByteBuf copyDouble(double value) {
852         ByteBuf buf = buffer(8);
853         buf.writeDouble(value);
854         return buf;
855     }
856 
857     /**
858      * Create a new big-endian buffer that holds a sequence of the specified 64-bit floating point numbers.
859      */
860     public static ByteBuf copyDouble(double... values) {
861         if (values == null || values.length == 0) {
862             return EMPTY_BUFFER;
863         }
864         ByteBuf buffer = buffer(values.length * 8);
865         for (double v: values) {
866             buffer.writeDouble(v);
867         }
868         return buffer;
869     }
870 
871     /**
872      * Return a unreleasable view on the given {@link ByteBuf} which will just ignore release and retain calls.
873      */
874     public static ByteBuf unreleasableBuffer(ByteBuf buf) {
875         return new UnreleasableByteBuf(buf);
876     }
877 
878     /**
879      * Wrap the given {@link ByteBuf}s in an unmodifiable {@link ByteBuf}. Be aware the returned {@link ByteBuf} will
880      * not try to slice the given {@link ByteBuf}s to reduce GC-Pressure.
881      */
882     public static ByteBuf unmodifiableBuffer(ByteBuf... buffers) {
883         return new FixedCompositeByteBuf(ALLOC, buffers);
884     }
885 
886     private Unpooled() {
887         // Unused
888     }
889 }