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