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