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.CompositeByteBuf; 17 18 import hunt.net.buffer.AbstractByteBuf; 19 import hunt.net.buffer.AbstractByteBufAllocator; 20 import hunt.net.buffer.AbstractReferenceCountedByteBuf; 21 import hunt.net.buffer.AbstractUnpooledSlicedByteBuf; 22 import hunt.net.buffer.ByteBuf; 23 import hunt.net.buffer.ByteBufAllocator; 24 import hunt.net.buffer.ByteBufUtil; 25 import hunt.net.buffer.ByteProcessor; 26 import hunt.net.buffer.ReferenceCountUtil; 27 import hunt.net.buffer.Unpooled; 28 29 import hunt.Byte; 30 import hunt.io.ByteBuffer; 31 import hunt.io.BufferUtils; 32 import hunt.collection.Collections; 33 import hunt.collection.ArrayList; 34 import hunt.collection.List; 35 import hunt.Double; 36 import hunt.Exceptions; 37 import hunt.Float; 38 import hunt.logging; 39 import hunt.net.Exceptions; 40 import hunt.stream.Common; 41 import hunt.util.StringBuilder; 42 import hunt.util.ByteOrder; 43 import hunt.util.Common; 44 45 import std.algorithm; 46 import std.conv; 47 import std.format; 48 import std.concurrency : initOnce; 49 import std.range; 50 51 // import io.netty.util.ByteProcessor; 52 // import io.netty.util.IllegalReferenceCountException; 53 // import io.netty.util.ReferenceCountUtil; 54 // import io.netty.util.internal.EmptyArrays; 55 // import io.netty.util.internal.RecyclableArrayList; 56 57 // import java.io.IOException; 58 // import java.io.InputStream; 59 // import java.io.OutputStream; 60 // import java.nio.ByteBuffer; 61 // import java.nio.ByteOrder; 62 // import java.nio.channels.FileChannel; 63 // import java.nio.channels.GatheringByteChannel; 64 // import java.nio.channels.ScatteringByteChannel; 65 // import java.util.ArrayList; 66 // import java.util.Arrays; 67 // import java.util.Collection; 68 // import java.util.Collections; 69 // import java.util.ConcurrentModificationException; 70 // import java.util.Iterator; 71 // import java.util.List; 72 // import java.util.NoSuchElementException; 73 74 // import static io.netty.util.internal.ObjectUtil.checkNotNull; 75 76 /** 77 * A virtual buffer which shows multiple buffers as a single merged buffer. It is recommended to use 78 * {@link ByteBufAllocator#compositeBuffer()} or {@link Unpooled#wrappedBuffer(ByteBuf...)} instead of calling the 79 * constructor explicitly. 80 */ 81 class CompositeByteBuf : AbstractReferenceCountedByteBuf, Iterable!(ByteBuf) { 82 83 private static ByteBuffer EMPTY_NIO_BUFFER() { 84 __gshared ByteBuffer inst; 85 return initOnce!inst(Unpooled.EMPTY_BUFFER.nioBuffer()); 86 } 87 // private static final Iterator!(ByteBuf) EMPTY_ITERATOR = Collections.<ByteBuf>emptyList().iterator(); 88 89 private ByteBufAllocator _alloc; 90 private bool direct; 91 private int _maxNumComponents; 92 93 private int componentCount; 94 private Component[] components; // resized when needed 95 96 private bool freed; 97 98 private this(ByteBufAllocator alloc, bool direct, int maxNumComponents, int initSize) { 99 super(AbstractByteBufAllocator.DEFAULT_MAX_CAPACITY); 100 if (alloc is null) { 101 throw new NullPointerException("alloc"); 102 } 103 if (maxNumComponents < 1) { 104 throw new IllegalArgumentException( 105 "maxNumComponents: " ~ maxNumComponents.to!string() ~ " (expected: >= 1)"); 106 } 107 this._alloc = alloc; 108 this.direct = direct; 109 this._maxNumComponents = maxNumComponents; 110 components = newCompArray(initSize, maxNumComponents); 111 } 112 113 this(ByteBufAllocator alloc, bool direct, int maxNumComponents) { 114 this(alloc, direct, maxNumComponents, 0); 115 } 116 117 this(ByteBufAllocator alloc, bool direct, int maxNumComponents, ByteBuf[] buffers...) { 118 this(alloc, direct, maxNumComponents, buffers, 0); 119 } 120 121 this(ByteBufAllocator alloc, bool direct, int maxNumComponents, 122 ByteBuf[] buffers, int offset) { 123 this(alloc, direct, maxNumComponents, cast(int)buffers.length - offset); 124 125 addComponents0(false, 0, buffers, offset); 126 consolidateIfNeeded(); 127 setIndex0(0, capacity()); 128 } 129 130 // this(ByteBufAllocator alloc, bool direct, int maxNumComponents, Iterable!(ByteBuf) buffers) { 131 // this(alloc, direct, maxNumComponents, 132 // buffers instanceof Collection ? ((Collection!(ByteBuf)) buffers).size() : 0); 133 134 // addComponents(false, 0, buffers); 135 // setIndex(0, capacity()); 136 // } 137 138 static ByteWrapper!(byte[]) BYTE_ARRAY_WRAPPER() { 139 __gshared ByteWrapper!(byte[]) inst; 140 return initOnce!inst(createByteWrapper()); 141 } 142 143 private static ByteWrapper!(byte[]) createByteWrapper() { 144 return new class ByteWrapper!(byte[]) { 145 override 146 ByteBuf wrap(byte[] bytes) { 147 return Unpooled.wrappedBuffer(bytes); 148 } 149 override 150 bool isEmpty(byte[] bytes) { 151 return bytes.length == 0; 152 } 153 }; 154 } 155 156 157 static final ByteWrapper!(ByteBuffer) BYTE_BUFFER_WRAPPER() { 158 __gshared ByteWrapper!(ByteBuffer) inst; 159 return initOnce!inst(createByteBufferWrapper()); 160 } 161 162 private static ByteWrapper!(ByteBuffer) createByteBufferWrapper() { 163 return new class ByteWrapper!(ByteBuffer) { 164 override 165 ByteBuf wrap(ByteBuffer bytes) { 166 return Unpooled.wrappedBuffer(bytes); 167 } 168 override 169 bool isEmpty(ByteBuffer bytes) { 170 return !bytes.hasRemaining(); 171 } 172 }; 173 } 174 175 this(T)(ByteBufAllocator alloc, bool direct, int maxNumComponents, 176 ByteWrapper!(T) wrapper, T[] buffers, int offset) { 177 this(alloc, direct, maxNumComponents, cast(int)buffers.length - offset); 178 179 addComponents0(false, 0, wrapper, buffers, offset); 180 consolidateIfNeeded(); 181 setIndex(0, capacity()); 182 } 183 184 private static Component[] newCompArray(int initComponents, int maxNumComponents) { 185 int capacityGuess = min(AbstractByteBufAllocator.DEFAULT_MAX_COMPONENTS, maxNumComponents); 186 return new Component[max(initComponents, capacityGuess)]; 187 } 188 189 // Special constructor used by WrappedCompositeByteBuf 190 this(ByteBufAllocator alloc) { 191 super(int.max); 192 this._alloc = alloc; 193 direct = false; 194 _maxNumComponents = 0; 195 components = null; 196 } 197 198 /** 199 * Add the given {@link ByteBuf}. 200 * <p> 201 * Be aware that this method does not increase the {@code writerIndex} of the {@link CompositeByteBuf}. 202 * If you need to have it increased use {@link #addComponent(bool, ByteBuf)}. 203 * <p> 204 * {@link ByteBuf#release()} ownership of {@code buffer} is transferred to this {@link CompositeByteBuf}. 205 * @param buffer the {@link ByteBuf} to add. {@link ByteBuf#release()} ownership is transferred to this 206 * {@link CompositeByteBuf}. 207 */ 208 CompositeByteBuf addComponent(ByteBuf buffer) { 209 return addComponent(false, buffer); 210 } 211 212 /** 213 * Add the given {@link ByteBuf}s. 214 * <p> 215 * Be aware that this method does not increase the {@code writerIndex} of the {@link CompositeByteBuf}. 216 * If you need to have it increased use {@link #addComponents(bool, ByteBuf[])}. 217 * <p> 218 * {@link ByteBuf#release()} ownership of all {@link ByteBuf} objects in {@code buffers} is transferred to this 219 * {@link CompositeByteBuf}. 220 * @param buffers the {@link ByteBuf}s to add. {@link ByteBuf#release()} ownership of all {@link ByteBuf#release()} 221 * ownership of all {@link ByteBuf} objects is transferred to this {@link CompositeByteBuf}. 222 */ 223 CompositeByteBuf addComponents(ByteBuf[] buffers...) { 224 return addComponents(false, buffers); 225 } 226 227 /** 228 * Add the given {@link ByteBuf}s. 229 * <p> 230 * Be aware that this method does not increase the {@code writerIndex} of the {@link CompositeByteBuf}. 231 * If you need to have it increased use {@link #addComponents(bool, Iterable)}. 232 * <p> 233 * {@link ByteBuf#release()} ownership of all {@link ByteBuf} objects in {@code buffers} is transferred to this 234 * {@link CompositeByteBuf}. 235 * @param buffers the {@link ByteBuf}s to add. {@link ByteBuf#release()} ownership of all {@link ByteBuf#release()} 236 * ownership of all {@link ByteBuf} objects is transferred to this {@link CompositeByteBuf}. 237 */ 238 CompositeByteBuf addComponents(Iterable!(ByteBuf) buffers) { 239 return addComponents(false, buffers); 240 } 241 242 /** 243 * Add the given {@link ByteBuf} on the specific index. 244 * <p> 245 * Be aware that this method does not increase the {@code writerIndex} of the {@link CompositeByteBuf}. 246 * If you need to have it increased use {@link #addComponent(bool, int, ByteBuf)}. 247 * <p> 248 * {@link ByteBuf#release()} ownership of {@code buffer} is transferred to this {@link CompositeByteBuf}. 249 * @param cIndex the index on which the {@link ByteBuf} will be added. 250 * @param buffer the {@link ByteBuf} to add. {@link ByteBuf#release()} ownership is transferred to this 251 * {@link CompositeByteBuf}. 252 */ 253 CompositeByteBuf addComponent(int cIndex, ByteBuf buffer) { 254 return addComponent(false, cIndex, buffer); 255 } 256 257 /** 258 * Add the given {@link ByteBuf} and increase the {@code writerIndex} if {@code increaseWriterIndex} is 259 * {@code true}. 260 * 261 * {@link ByteBuf#release()} ownership of {@code buffer} is transferred to this {@link CompositeByteBuf}. 262 * @param buffer the {@link ByteBuf} to add. {@link ByteBuf#release()} ownership is transferred to this 263 * {@link CompositeByteBuf}. 264 */ 265 CompositeByteBuf addComponent(bool increaseWriterIndex, ByteBuf buffer) { 266 return addComponent(increaseWriterIndex, componentCount, buffer); 267 } 268 269 /** 270 * Add the given {@link ByteBuf}s and increase the {@code writerIndex} if {@code increaseWriterIndex} is 271 * {@code true}. 272 * 273 * {@link ByteBuf#release()} ownership of all {@link ByteBuf} objects in {@code buffers} is transferred to this 274 * {@link CompositeByteBuf}. 275 * @param buffers the {@link ByteBuf}s to add. {@link ByteBuf#release()} ownership of all {@link ByteBuf#release()} 276 * ownership of all {@link ByteBuf} objects is transferred to this {@link CompositeByteBuf}. 277 */ 278 CompositeByteBuf addComponents(bool increaseWriterIndex, ByteBuf[] buffers...) { 279 checkNotNull(buffers, "buffers"); 280 addComponents0(increaseWriterIndex, componentCount, buffers, 0); 281 consolidateIfNeeded(); 282 return this; 283 } 284 285 /** 286 * Add the given {@link ByteBuf}s and increase the {@code writerIndex} if {@code increaseWriterIndex} is 287 * {@code true}. 288 * 289 * {@link ByteBuf#release()} ownership of all {@link ByteBuf} objects in {@code buffers} is transferred to this 290 * {@link CompositeByteBuf}. 291 * @param buffers the {@link ByteBuf}s to add. {@link ByteBuf#release()} ownership of all {@link ByteBuf#release()} 292 * ownership of all {@link ByteBuf} objects is transferred to this {@link CompositeByteBuf}. 293 */ 294 CompositeByteBuf addComponents(bool increaseWriterIndex, Iterable!(ByteBuf) buffers) { 295 return addComponents(increaseWriterIndex, componentCount, buffers); 296 } 297 298 /** 299 * Add the given {@link ByteBuf} on the specific index and increase the {@code writerIndex} 300 * if {@code increaseWriterIndex} is {@code true}. 301 * 302 * {@link ByteBuf#release()} ownership of {@code buffer} is transferred to this {@link CompositeByteBuf}. 303 * @param cIndex the index on which the {@link ByteBuf} will be added. 304 * @param buffer the {@link ByteBuf} to add. {@link ByteBuf#release()} ownership is transferred to this 305 * {@link CompositeByteBuf}. 306 */ 307 CompositeByteBuf addComponent(bool increaseWriterIndex, int cIndex, ByteBuf buffer) { 308 checkNotNull(buffer, "buffer"); 309 addComponent0(increaseWriterIndex, cIndex, buffer); 310 consolidateIfNeeded(); 311 return this; 312 } 313 314 /** 315 * Precondition is that {@code buffer !is null}. 316 */ 317 private int addComponent0(bool increaseWriterIndex, int cIndex, ByteBuf buffer) { 318 assert(buffer !is null); 319 bool wasAdded = false; 320 try { 321 checkComponentIndex(cIndex); 322 323 // No need to consolidate - just add a component to the list. 324 Component c = newComponent(buffer, 0); 325 int readableBytes = c.length(); 326 327 addComp(cIndex, c); 328 wasAdded = true; 329 if (readableBytes > 0 && cIndex < componentCount - 1) { 330 updateComponentOffsets(cIndex); 331 } else if (cIndex > 0) { 332 c.reposition(components[cIndex - 1].endOffset); 333 } 334 if (increaseWriterIndex) { 335 _writerIndex += readableBytes; 336 } 337 return cIndex; 338 } finally { 339 if (!wasAdded) { 340 buffer.release(); 341 } 342 } 343 } 344 345 private Component newComponent(ByteBuf buf, int offset) { 346 if (checkAccessible && !buf.isAccessible()) { 347 throw new IllegalReferenceCountException(0); 348 } 349 int srcIndex = buf.readerIndex(), len = buf.readableBytes(); 350 ByteBuf _slice = null; 351 // unwrap if already sliced 352 AbstractUnpooledSlicedByteBuf slicedBuffer = cast(AbstractUnpooledSlicedByteBuf) buf; 353 if (slicedBuffer !is null) { 354 srcIndex += slicedBuffer.idx(0); 355 _slice = buf; 356 buf = buf.unwrap(); 357 } else { 358 // TODO: Tasks pending completion -@zxp at 8/16/2019, 6:25:33 PM 359 // 360 // implementationMissing(false); 361 // if (buf instanceof PooledSlicedByteBuf) { 362 // srcIndex += ((PooledSlicedByteBuf) buf).adjustment; 363 // _slice = buf; 364 // buf = buf.unwrap(); 365 // } 366 } 367 return new Component(buf, srcIndex, offset, len, _slice); // .order(ByteOrder.BigEndian) 368 } 369 370 /** 371 * Add the given {@link ByteBuf}s on the specific index 372 * <p> 373 * Be aware that this method does not increase the {@code writerIndex} of the {@link CompositeByteBuf}. 374 * If you need to have it increased you need to handle it by your own. 375 * <p> 376 * {@link ByteBuf#release()} ownership of all {@link ByteBuf} objects in {@code buffers} is transferred to this 377 * {@link CompositeByteBuf}. 378 * @param cIndex the index on which the {@link ByteBuf} will be added. {@link ByteBuf#release()} ownership of all 379 * {@link ByteBuf#release()} ownership of all {@link ByteBuf} objects is transferred to this 380 * {@link CompositeByteBuf}. 381 * @param buffers the {@link ByteBuf}s to add. {@link ByteBuf#release()} ownership of all {@link ByteBuf#release()} 382 * ownership of all {@link ByteBuf} objects is transferred to this {@link CompositeByteBuf}. 383 */ 384 CompositeByteBuf addComponents(int cIndex, ByteBuf[] buffers...) { 385 checkNotNull(buffers, "buffers"); 386 addComponents0(false, cIndex, buffers, 0); 387 consolidateIfNeeded(); 388 return this; 389 } 390 391 private CompositeByteBuf addComponents0(bool increaseWriterIndex, 392 int cIndex, ByteBuf[] buffers, int arrOffset) { 393 int len = cast(int)buffers.length; 394 int count = len - arrOffset; 395 // only set ci after we've shifted so that finally block logic is always correct 396 int ci = int.max; 397 try { 398 checkComponentIndex(cIndex); 399 shiftComps(cIndex, count); // will increase componentCount 400 int nextOffset = cIndex > 0 ? components[cIndex - 1].endOffset : 0; 401 for (ci = cIndex; arrOffset < len; arrOffset++, ci++) { 402 ByteBuf b = buffers[arrOffset]; 403 if (b is null) { 404 break; 405 } 406 Component c = newComponent(b, nextOffset); 407 components[ci] = c; 408 nextOffset = c.endOffset; 409 } 410 return this; 411 } finally { 412 // ci is now the index following the last successfully added component 413 if (ci < componentCount) { 414 if (ci < cIndex + count) { 415 // we bailed early 416 removeCompRange(ci, cIndex + count); 417 for (; arrOffset < len; ++arrOffset) { 418 ReferenceCountUtil.safeRelease(buffers[arrOffset]); 419 } 420 } 421 updateComponentOffsets(ci); // only need to do this here for components after the added ones 422 } 423 if (increaseWriterIndex && ci > cIndex && ci <= componentCount) { 424 _writerIndex += components[ci - 1].endOffset - components[cIndex].offset; 425 } 426 } 427 } 428 429 private int addComponents0(T)(bool increaseWriterIndex, int cIndex, 430 ByteWrapper!(T) wrapper, T[] buffers, int offset) { 431 checkComponentIndex(cIndex); 432 433 // No need for consolidation 434 for (int i = offset, len = cast(int)buffers.length; i < len; i++) { 435 T b = buffers[i]; 436 if (b is null) { 437 break; 438 } 439 if (!wrapper.isEmpty(b)) { 440 cIndex = addComponent0(increaseWriterIndex, cIndex, wrapper.wrap(b)) + 1; 441 int size = componentCount; 442 if (cIndex > size) { 443 cIndex = size; 444 } 445 } 446 } 447 return cIndex; 448 } 449 450 /** 451 * Add the given {@link ByteBuf}s on the specific index 452 * 453 * Be aware that this method does not increase the {@code writerIndex} of the {@link CompositeByteBuf}. 454 * If you need to have it increased you need to handle it by your own. 455 * <p> 456 * {@link ByteBuf#release()} ownership of all {@link ByteBuf} objects in {@code buffers} is transferred to this 457 * {@link CompositeByteBuf}. 458 * @param cIndex the index on which the {@link ByteBuf} will be added. 459 * @param buffers the {@link ByteBuf}s to add. {@link ByteBuf#release()} ownership of all 460 * {@link ByteBuf#release()} ownership of all {@link ByteBuf} objects is transferred to this 461 * {@link CompositeByteBuf}. 462 */ 463 CompositeByteBuf addComponents(int cIndex, Iterable!(ByteBuf) buffers) { 464 return addComponents(false, cIndex, buffers); 465 } 466 467 /** 468 * Add the given {@link ByteBuf} and increase the {@code writerIndex} if {@code increaseWriterIndex} is 469 * {@code true}. If the provided buffer is a {@link CompositeByteBuf} itself, a "shallow copy" of its 470 * readable components will be performed. Thus the actual number of new components added may vary 471 * and in particular will be zero if the provided buffer is not readable. 472 * <p> 473 * {@link ByteBuf#release()} ownership of {@code buffer} is transferred to this {@link CompositeByteBuf}. 474 * @param buffer the {@link ByteBuf} to add. {@link ByteBuf#release()} ownership is transferred to this 475 * {@link CompositeByteBuf}. 476 */ 477 CompositeByteBuf addFlattenedComponents(bool increaseWriterIndex, ByteBuf buffer) { 478 checkNotNull(buffer, "buffer"); 479 int ridx = buffer.readerIndex(); 480 int widx = buffer.writerIndex(); 481 if (ridx == widx) { 482 buffer.release(); 483 return this; 484 } 485 CompositeByteBuf from = cast(CompositeByteBuf) buffer; 486 if (from is null) { 487 addComponent0(increaseWriterIndex, componentCount, buffer); 488 consolidateIfNeeded(); 489 return this; 490 } 491 from.checkIndex(ridx, widx - ridx); 492 Component[] fromComponents = from.components; 493 int compCountBefore = componentCount; 494 int writerIndexBefore = writerIndex; 495 try { 496 for (int cidx = from.toComponentIndex0(ridx), newOffset = capacity();; cidx++) { 497 Component component = fromComponents[cidx]; 498 int compOffset = component.offset; 499 int fromIdx = max(ridx, compOffset); 500 int toIdx = min(widx, component.endOffset); 501 int len = toIdx - fromIdx; 502 if (len > 0) { // skip empty components 503 // Note that it's safe to just retain the unwrapped buf here, even in the case 504 // of PooledSlicedByteBufs - those slices will still be properly released by the 505 // source Component's free() method. 506 addComp(componentCount, new Component( 507 component.buf.retain(), component.idx(fromIdx), newOffset, len, null)); 508 } 509 if (widx == toIdx) { 510 break; 511 } 512 newOffset += len; 513 } 514 if (increaseWriterIndex) { 515 writerIndex = writerIndexBefore + (widx - ridx); 516 } 517 consolidateIfNeeded(); 518 buffer.release(); 519 buffer = null; 520 return this; 521 } finally { 522 if (buffer !is null) { 523 // if we did not succeed, attempt to rollback any components that were added 524 if (increaseWriterIndex) { 525 writerIndex = writerIndexBefore; 526 } 527 for (int cidx = componentCount - 1; cidx >= compCountBefore; cidx--) { 528 components[cidx].free(); 529 removeComp(cidx); 530 } 531 } 532 } 533 } 534 535 // TODO optimize further, similar to ByteBuf[] version 536 // (difference here is that we don't know *always* know precise size increase in advance, 537 // but we do in the most common case that the Iterable is a Collection) 538 private CompositeByteBuf addComponents(bool increaseIndex, int cIndex, Iterable!(ByteBuf) buffers) { 539 // if (buffers instanceof ByteBuf) { 540 // // If buffers also implements ByteBuf (e.g. CompositeByteBuf), it has to go to addComponent(ByteBuf). 541 // return addComponent(increaseIndex, cIndex, (ByteBuf) buffers); 542 // } 543 // checkNotNull(buffers, "buffers"); 544 // Iterator!(ByteBuf) it = buffers.iterator(); 545 // try { 546 // checkComponentIndex(cIndex); 547 548 // // No need for consolidation 549 // while (it.hasNext()) { 550 // ByteBuf b = it.next(); 551 // if (b is null) { 552 // break; 553 // } 554 // cIndex = addComponent0(increaseIndex, cIndex, b) + 1; 555 // cIndex = min(cIndex, componentCount); 556 // } 557 // } finally { 558 // while (it.hasNext()) { 559 // ReferenceCountUtil.safeRelease(it.next()); 560 // } 561 // } 562 // consolidateIfNeeded(); 563 implementationMissing(false); 564 return this; 565 } 566 567 /** 568 * This should only be called as last operation from a method as this may adjust the underlying 569 * array of components and so affect the index etc. 570 */ 571 private void consolidateIfNeeded() { 572 // Consolidate if the number of components will exceed the allowed maximum by the current 573 // operation. 574 int size = componentCount; 575 if (size > _maxNumComponents) { 576 int capacity = components[size - 1].endOffset; 577 578 ByteBuf consolidated = allocBuffer(capacity); 579 lastAccessed = null; 580 581 // We're not using foreach to avoid creating an iterator. 582 for (int i = 0; i < size; i ++) { 583 components[i].transferTo(consolidated); 584 } 585 586 components[0] = new Component(consolidated, 0, 0, capacity, consolidated); 587 removeCompRange(1, size); 588 } 589 } 590 591 private void checkComponentIndex(int cIndex) { 592 ensureAccessible(); 593 if (cIndex < 0 || cIndex > componentCount) { 594 throw new IndexOutOfBoundsException(format( 595 "cIndex: %d (expected: >= 0 && <= numComponents(%d))", 596 cIndex, componentCount)); 597 } 598 } 599 600 private void checkComponentIndex(int cIndex, int numComponents) { 601 ensureAccessible(); 602 if (cIndex < 0 || cIndex + numComponents > componentCount) { 603 throw new IndexOutOfBoundsException(format( 604 "cIndex: %d, numComponents: %d " ~ 605 "(expected: cIndex >= 0 && cIndex + numComponents <= totalNumComponents(%d))", 606 cIndex, numComponents, componentCount)); 607 } 608 } 609 610 private void updateComponentOffsets(int cIndex) { 611 int size = componentCount; 612 if (size <= cIndex) { 613 return; 614 } 615 616 int nextIndex = cIndex > 0 ? components[cIndex - 1].endOffset : 0; 617 for (; cIndex < size; cIndex++) { 618 Component c = components[cIndex]; 619 c.reposition(nextIndex); 620 nextIndex = c.endOffset; 621 } 622 } 623 624 /** 625 * Remove the {@link ByteBuf} from the given index. 626 * 627 * @param cIndex the index on from which the {@link ByteBuf} will be remove 628 */ 629 CompositeByteBuf removeComponent(int cIndex) { 630 checkComponentIndex(cIndex); 631 Component comp = components[cIndex]; 632 if (lastAccessed == comp) { 633 lastAccessed = null; 634 } 635 comp.free(); 636 removeComp(cIndex); 637 if (comp.length() > 0) { 638 // Only need to call updateComponentOffsets if the length was > 0 639 updateComponentOffsets(cIndex); 640 } 641 return this; 642 } 643 644 /** 645 * Remove the number of {@link ByteBuf}s starting from the given index. 646 * 647 * @param cIndex the index on which the {@link ByteBuf}s will be started to removed 648 * @param numComponents the number of components to remove 649 */ 650 CompositeByteBuf removeComponents(int cIndex, int numComponents) { 651 checkComponentIndex(cIndex, numComponents); 652 653 if (numComponents == 0) { 654 return this; 655 } 656 int endIndex = cIndex + numComponents; 657 bool needsUpdate = false; 658 for (int i = cIndex; i < endIndex; ++i) { 659 Component c = components[i]; 660 if (c.length() > 0) { 661 needsUpdate = true; 662 } 663 if (lastAccessed == c) { 664 lastAccessed = null; 665 } 666 c.free(); 667 } 668 removeCompRange(cIndex, endIndex); 669 670 if (needsUpdate) { 671 // Only need to call updateComponentOffsets if the length was > 0 672 updateComponentOffsets(cIndex); 673 } 674 return this; 675 } 676 677 // override 678 InputRange!(ByteBuf) iterator() { 679 ensureAccessible(); 680 // return componentCount == 0 ? EMPTY_ITERATOR : new CompositeByteBufIterator(); 681 implementationMissing(false); 682 return null; 683 } 684 685 int opApply(scope int delegate(ref ByteBuf) dg) { 686 if(dg is null) 687 throw new NullPointerException(); 688 689 int result = 0; 690 foreach(Component v; components) { 691 ByteBuf b = v.slice(); 692 result = dg(b); 693 if(result != 0) return result; 694 } 695 return result; 696 697 } 698 699 override 700 protected int forEachByteAsc0(int start, int end, ByteProcessor processor) { 701 if (end <= start) { 702 return -1; 703 } 704 for (int i = toComponentIndex0(start), length = end - start; length > 0; i++) { 705 Component c = components[i]; 706 if (c.offset == c.endOffset) { 707 continue; // empty 708 } 709 ByteBuf s = c.buf; 710 int localStart = c.idx(start); 711 int localLength = min(length, c.endOffset - start); 712 // avoid additional checks in AbstractByteBuf case 713 AbstractByteBuf buffer = cast(AbstractByteBuf) s; 714 int result = 0; 715 if(buffer is null) 716 result = s.forEachByte(localStart, localLength, processor); 717 else 718 result = buffer.forEachByteAsc0(localStart, localStart + localLength, processor); 719 720 if (result != -1) { 721 return result - c.adjustment; 722 } 723 start += localLength; 724 length -= localLength; 725 } 726 return -1; 727 } 728 729 override 730 protected int forEachByteDesc0(int rStart, int rEnd, ByteProcessor processor) { 731 if (rEnd > rStart) { // rStart *and* rEnd are inclusive 732 return -1; 733 } 734 for (int i = toComponentIndex0(rStart), length = 1 + rStart - rEnd; length > 0; i--) { 735 Component c = components[i]; 736 if (c.offset == c.endOffset) { 737 continue; // empty 738 } 739 ByteBuf s = c.buf; 740 int localRStart = c.idx(length + rEnd); 741 int localLength = min(length, localRStart), localIndex = localRStart - localLength; 742 // avoid additional checks in AbstractByteBuf case 743 int result = 0; 744 AbstractByteBuf buf = cast(AbstractByteBuf) s; 745 if(buf is null) 746 result = s.forEachByteDesc(localIndex, localLength, processor); 747 else 748 result = buf.forEachByteDesc0(localRStart - 1, localIndex, processor); 749 750 if (result != -1) { 751 return result - c.adjustment; 752 } 753 length -= localLength; 754 } 755 return -1; 756 } 757 758 /** 759 * Same with {@link #slice(int, int)} except that this method returns a list. 760 */ 761 List!(ByteBuf) decompose(int offset, int length) { 762 checkIndex(offset, length); 763 if (length == 0) { 764 return Collections.emptyList!(ByteBuf)(); 765 } 766 767 int componentId = toComponentIndex0(offset); 768 int bytesToSlice = length; 769 // The first component 770 Component firstC = components[componentId]; 771 772 ByteBuf _slice = firstC.buf.slice(firstC.idx(offset), min(firstC.endOffset - offset, bytesToSlice)); 773 bytesToSlice -= _slice.readableBytes(); 774 775 if (bytesToSlice == 0) { 776 return Collections.singletonList(_slice); 777 } 778 779 List!(ByteBuf) sliceList = new ArrayList!(ByteBuf)(componentCount - componentId); 780 sliceList.add(_slice); 781 782 // Add all the slices until there is nothing more left and then return the List. 783 do { 784 Component component = components[++componentId]; 785 _slice = component.buf.slice(component.idx(component.offset), min(component.length(), bytesToSlice)); 786 bytesToSlice -= _slice.readableBytes(); 787 sliceList.add(_slice); 788 } while (bytesToSlice > 0); 789 790 return sliceList; 791 } 792 793 override 794 bool isDirect() { 795 int size = componentCount; 796 if (size == 0) { 797 return false; 798 } 799 for (int i = 0; i < size; i++) { 800 if (!components[i].buf.isDirect()) { 801 return false; 802 } 803 } 804 return true; 805 } 806 807 override 808 bool hasArray() { 809 switch (componentCount) { 810 case 0: 811 return true; 812 case 1: 813 return components[0].buf.hasArray(); 814 default: 815 return false; 816 } 817 } 818 819 override 820 byte[] array() { 821 switch (componentCount) { 822 case 0: 823 return []; 824 case 1: 825 return components[0].buf.array(); 826 default: 827 throw new UnsupportedOperationException(); 828 } 829 } 830 831 override 832 int arrayOffset() { 833 switch (componentCount) { 834 case 0: 835 return 0; 836 case 1: 837 Component c = components[0]; 838 return c.idx(c.buf.arrayOffset()); 839 default: 840 throw new UnsupportedOperationException(); 841 } 842 } 843 844 override 845 bool hasMemoryAddress() { 846 switch (componentCount) { 847 case 0: 848 return Unpooled.EMPTY_BUFFER.hasMemoryAddress(); 849 case 1: 850 return components[0].buf.hasMemoryAddress(); 851 default: 852 return false; 853 } 854 } 855 856 override 857 long memoryAddress() { 858 switch (componentCount) { 859 case 0: 860 return Unpooled.EMPTY_BUFFER.memoryAddress(); 861 case 1: 862 Component c = components[0]; 863 return c.buf.memoryAddress() + c.adjustment; 864 default: 865 throw new UnsupportedOperationException(); 866 } 867 } 868 869 override 870 int capacity() { 871 int size = componentCount; 872 return size > 0 ? components[size - 1].endOffset : 0; 873 } 874 875 override 876 CompositeByteBuf capacity(int newCapacity) { 877 checkNewCapacity(newCapacity); 878 879 int size = componentCount, oldCapacity = capacity(); 880 if (newCapacity > oldCapacity) { 881 int paddingLength = newCapacity - oldCapacity; 882 ByteBuf padding = allocBuffer(paddingLength).setIndex(0, paddingLength); 883 addComponent0(false, size, padding); 884 if (componentCount >= _maxNumComponents) { 885 // FIXME: No need to create a padding buffer and consolidate. 886 // Just create a big single buffer and put the current content there. 887 consolidateIfNeeded(); 888 } 889 } else if (newCapacity < oldCapacity) { 890 lastAccessed = null; 891 int i = size - 1; 892 for (int bytesToTrim = oldCapacity - newCapacity; i >= 0; i--) { 893 Component c = components[i]; 894 int cLength = c.length(); 895 if (bytesToTrim < cLength) { 896 // Trim the last component 897 c.endOffset -= bytesToTrim; 898 ByteBuf _slice = c._slice; 899 if (_slice !is null) { 900 // We must replace the cached slice with a derived one to ensure that 901 // it can later be released properly in the case of PooledSlicedByteBuf. 902 c._slice = _slice.slice(0, c.length()); 903 } 904 break; 905 } 906 c.free(); 907 bytesToTrim -= cLength; 908 } 909 removeCompRange(i + 1, size); 910 911 if (readerIndex() > newCapacity) { 912 setIndex0(newCapacity, newCapacity); 913 } else if (writerIndex > newCapacity) { 914 writerIndex = newCapacity; 915 } 916 } 917 return this; 918 } 919 920 override 921 ByteBufAllocator alloc() { 922 return _alloc; 923 } 924 925 override 926 ByteOrder order() { 927 return ByteOrder.BigEndian; 928 } 929 930 /** 931 * Return the current number of {@link ByteBuf}'s that are composed in this instance 932 */ 933 int numComponents() { 934 return componentCount; 935 } 936 937 /** 938 * Return the max number of {@link ByteBuf}'s that are composed in this instance 939 */ 940 int maxNumComponents() { 941 return _maxNumComponents; 942 } 943 944 /** 945 * Return the index for the given offset 946 */ 947 int toComponentIndex(int offset) { 948 checkIndex(offset); 949 return toComponentIndex0(offset); 950 } 951 952 private int toComponentIndex0(int offset) { 953 int size = componentCount; 954 if (offset == 0) { // fast-path zero offset 955 for (int i = 0; i < size; i++) { 956 if (components[i].endOffset > 0) { 957 return i; 958 } 959 } 960 } 961 if (size <= 2) { // fast-path for 1 and 2 component count 962 return size == 1 || offset < components[0].endOffset ? 0 : 1; 963 } 964 for (int low = 0, high = size; low <= high;) { 965 int mid = low + high >>> 1; 966 Component c = components[mid]; 967 if (offset >= c.endOffset) { 968 low = mid + 1; 969 } else if (offset < c.offset) { 970 high = mid - 1; 971 } else { 972 return mid; 973 } 974 } 975 976 throw new Error("should not reach here"); 977 } 978 979 int toByteIndex(int cIndex) { 980 checkComponentIndex(cIndex); 981 return components[cIndex].offset; 982 } 983 984 override 985 byte getByte(int index) { 986 Component c = findComponent(index); 987 return c.buf.getByte(c.idx(index)); 988 } 989 990 override 991 protected byte _getByte(int index) { 992 Component c = findComponent0(index); 993 return c.buf.getByte(c.idx(index)); 994 } 995 996 override 997 protected short _getShort(int index) { 998 Component c = findComponent0(index); 999 if (index + 2 <= c.endOffset) { 1000 return c.buf.getShort(c.idx(index)); 1001 } else if (order() == ByteOrder.BigEndian) { 1002 return cast(short) ((_getByte(index) & 0xff) << 8 | _getByte(index + 1) & 0xff); 1003 } else { 1004 return cast(short) (_getByte(index) & 0xff | (_getByte(index + 1) & 0xff) << 8); 1005 } 1006 } 1007 1008 override 1009 protected short _getShortLE(int index) { 1010 Component c = findComponent0(index); 1011 if (index + 2 <= c.endOffset) { 1012 return c.buf.getShortLE(c.idx(index)); 1013 } else if (order() == ByteOrder.BigEndian) { 1014 return cast(short) (_getByte(index) & 0xff | (_getByte(index + 1) & 0xff) << 8); 1015 } else { 1016 return cast(short) ((_getByte(index) & 0xff) << 8 | _getByte(index + 1) & 0xff); 1017 } 1018 } 1019 1020 override 1021 protected int _getUnsignedMedium(int index) { 1022 Component c = findComponent0(index); 1023 if (index + 3 <= c.endOffset) { 1024 return c.buf.getUnsignedMedium(c.idx(index)); 1025 } else if (order() == ByteOrder.BigEndian) { 1026 return (_getShort(index) & 0xffff) << 8 | _getByte(index + 2) & 0xff; 1027 } else { 1028 return _getShort(index) & 0xFFFF | (_getByte(index + 2) & 0xFF) << 16; 1029 } 1030 } 1031 1032 override 1033 protected int _getUnsignedMediumLE(int index) { 1034 Component c = findComponent0(index); 1035 if (index + 3 <= c.endOffset) { 1036 return c.buf.getUnsignedMediumLE(c.idx(index)); 1037 } else if (order() == ByteOrder.BigEndian) { 1038 return _getShortLE(index) & 0xffff | (_getByte(index + 2) & 0xff) << 16; 1039 } else { 1040 return (_getShortLE(index) & 0xffff) << 8 | _getByte(index + 2) & 0xff; 1041 } 1042 } 1043 1044 override 1045 protected int _getInt(int index) { 1046 Component c = findComponent0(index); 1047 if (index + 4 <= c.endOffset) { 1048 return c.buf.getInt(c.idx(index)); 1049 } else if (order() == ByteOrder.BigEndian) { 1050 return (_getShort(index) & 0xffff) << 16 | _getShort(index + 2) & 0xffff; 1051 } else { 1052 return _getShort(index) & 0xFFFF | (_getShort(index + 2) & 0xFFFF) << 16; 1053 } 1054 } 1055 1056 override 1057 protected int _getIntLE(int index) { 1058 Component c = findComponent0(index); 1059 if (index + 4 <= c.endOffset) { 1060 return c.buf.getIntLE(c.idx(index)); 1061 } else if (order() == ByteOrder.BigEndian) { 1062 return _getShortLE(index) & 0xffff | (_getShortLE(index + 2) & 0xffff) << 16; 1063 } else { 1064 return (_getShortLE(index) & 0xffff) << 16 | _getShortLE(index + 2) & 0xffff; 1065 } 1066 } 1067 1068 override 1069 protected long _getLong(int index) { 1070 Component c = findComponent0(index); 1071 if (index + 8 <= c.endOffset) { 1072 return c.buf.getLong(c.idx(index)); 1073 } else if (order() == ByteOrder.BigEndian) { 1074 return (_getInt(index) & 0xffffffffL) << 32 | _getInt(index + 4) & 0xffffffffL; 1075 } else { 1076 return _getInt(index) & 0xFFFFFFFFL | (_getInt(index + 4) & 0xFFFFFFFFL) << 32; 1077 } 1078 } 1079 1080 override 1081 protected long _getLongLE(int index) { 1082 Component c = findComponent0(index); 1083 if (index + 8 <= c.endOffset) { 1084 return c.buf.getLongLE(c.idx(index)); 1085 } else if (order() == ByteOrder.BigEndian) { 1086 return _getIntLE(index) & 0xffffffffL | (_getIntLE(index + 4) & 0xffffffffL) << 32; 1087 } else { 1088 return (_getIntLE(index) & 0xffffffffL) << 32 | _getIntLE(index + 4) & 0xffffffffL; 1089 } 1090 } 1091 1092 override 1093 CompositeByteBuf getBytes(int index, byte[] dst, int dstIndex, int length) { 1094 checkDstIndex(index, length, dstIndex, cast(int)dst.length); 1095 if (length == 0) { 1096 return this; 1097 } 1098 1099 int i = toComponentIndex0(index); 1100 while (length > 0) { 1101 Component c = components[i]; 1102 int localLength = min(length, c.endOffset - index); 1103 c.buf.getBytes(c.idx(index), dst, dstIndex, localLength); 1104 index += localLength; 1105 dstIndex += localLength; 1106 length -= localLength; 1107 i ++; 1108 } 1109 return this; 1110 } 1111 1112 override 1113 CompositeByteBuf getBytes(int index, ByteBuffer dst) { 1114 int limit = dst.limit(); 1115 int length = dst.remaining(); 1116 1117 checkIndex(index, length); 1118 if (length == 0) { 1119 return this; 1120 } 1121 1122 int i = toComponentIndex0(index); 1123 try { 1124 while (length > 0) { 1125 Component c = components[i]; 1126 int localLength = min(length, c.endOffset - index); 1127 dst.limit(dst.position() + localLength); 1128 c.buf.getBytes(c.idx(index), dst); 1129 index += localLength; 1130 length -= localLength; 1131 i ++; 1132 } 1133 } finally { 1134 dst.limit(limit); 1135 } 1136 return this; 1137 } 1138 1139 override 1140 CompositeByteBuf getBytes(int index, ByteBuf dst, int dstIndex, int length) { 1141 checkDstIndex(index, length, dstIndex, dst.capacity()); 1142 if (length == 0) { 1143 return this; 1144 } 1145 1146 int i = toComponentIndex0(index); 1147 while (length > 0) { 1148 Component c = components[i]; 1149 int localLength = min(length, c.endOffset - index); 1150 c.buf.getBytes(c.idx(index), dst, dstIndex, localLength); 1151 index += localLength; 1152 dstIndex += localLength; 1153 length -= localLength; 1154 i ++; 1155 } 1156 return this; 1157 } 1158 1159 // override 1160 // int getBytes(int index, GatheringByteChannel output, int length) { 1161 // int count = nioBufferCount(); 1162 // if (count == 1) { 1163 // return output.write(internalNioBuffer(index, length)); 1164 // } else { 1165 // long writtenBytes = output.write(nioBuffers(index, length)); 1166 // if (writtenBytes > int.max) { 1167 // return int.max; 1168 // } else { 1169 // return cast(int) writtenBytes; 1170 // } 1171 // } 1172 // } 1173 1174 // override 1175 // int getBytes(int index, FileChannel output, long position, int length) { 1176 // int count = nioBufferCount(); 1177 // if (count == 1) { 1178 // return output.write(internalNioBuffer(index, length), position); 1179 // } else { 1180 // long writtenBytes = 0; 1181 // foreach(ByteBuffer buf ; nioBuffers(index, length)) { 1182 // writtenBytes += output.write(buf, position + writtenBytes); 1183 // } 1184 // if (writtenBytes > int.max) { 1185 // return int.max; 1186 // } 1187 // return cast(int) writtenBytes; 1188 // } 1189 // } 1190 1191 override 1192 CompositeByteBuf getBytes(int index, OutputStream output, int length) { 1193 checkIndex(index, length); 1194 if (length == 0) { 1195 return this; 1196 } 1197 1198 int i = toComponentIndex0(index); 1199 while (length > 0) { 1200 Component c = components[i]; 1201 int localLength = min(length, c.endOffset - index); 1202 c.buf.getBytes(c.idx(index), output, localLength); 1203 index += localLength; 1204 length -= localLength; 1205 i ++; 1206 } 1207 return this; 1208 } 1209 1210 override 1211 CompositeByteBuf setByte(int index, int value) { 1212 Component c = findComponent(index); 1213 c.buf.setByte(c.idx(index), value); 1214 return this; 1215 } 1216 1217 override 1218 protected void _setByte(int index, int value) { 1219 Component c = findComponent0(index); 1220 c.buf.setByte(c.idx(index), value); 1221 } 1222 1223 override 1224 CompositeByteBuf setShort(int index, int value) { 1225 checkIndex(index, 2); 1226 _setShort(index, value); 1227 return this; 1228 } 1229 1230 override 1231 protected void _setShort(int index, int value) { 1232 Component c = findComponent0(index); 1233 if (index + 2 <= c.endOffset) { 1234 c.buf.setShort(c.idx(index), value); 1235 } else if (order() == ByteOrder.BigEndian) { 1236 _setByte(index, cast(byte) (value >>> 8)); 1237 _setByte(index + 1, cast(byte) value); 1238 } else { 1239 _setByte(index, cast(byte) value); 1240 _setByte(index + 1, cast(byte) (value >>> 8)); 1241 } 1242 } 1243 1244 override 1245 protected void _setShortLE(int index, int value) { 1246 Component c = findComponent0(index); 1247 if (index + 2 <= c.endOffset) { 1248 c.buf.setShortLE(c.idx(index), value); 1249 } else if (order() == ByteOrder.BigEndian) { 1250 _setByte(index, cast(byte) value); 1251 _setByte(index + 1, cast(byte) (value >>> 8)); 1252 } else { 1253 _setByte(index, cast(byte) (value >>> 8)); 1254 _setByte(index + 1, cast(byte) value); 1255 } 1256 } 1257 1258 override 1259 CompositeByteBuf setMedium(int index, int value) { 1260 checkIndex(index, 3); 1261 _setMedium(index, value); 1262 return this; 1263 } 1264 1265 override 1266 protected void _setMedium(int index, int value) { 1267 Component c = findComponent0(index); 1268 if (index + 3 <= c.endOffset) { 1269 c.buf.setMedium(c.idx(index), value); 1270 } else if (order() == ByteOrder.BigEndian) { 1271 _setShort(index, cast(short) (value >> 8)); 1272 _setByte(index + 2, cast(byte) value); 1273 } else { 1274 _setShort(index, cast(short) value); 1275 _setByte(index + 2, cast(byte) (value >>> 16)); 1276 } 1277 } 1278 1279 override 1280 protected void _setMediumLE(int index, int value) { 1281 Component c = findComponent0(index); 1282 if (index + 3 <= c.endOffset) { 1283 c.buf.setMediumLE(c.idx(index), value); 1284 } else if (order() == ByteOrder.BigEndian) { 1285 _setShortLE(index, cast(short) value); 1286 _setByte(index + 2, cast(byte) (value >>> 16)); 1287 } else { 1288 _setShortLE(index, cast(short) (value >> 8)); 1289 _setByte(index + 2, cast(byte) value); 1290 } 1291 } 1292 1293 override 1294 CompositeByteBuf setInt(int index, int value) { 1295 checkIndex(index, 4); 1296 _setInt(index, value); 1297 return this; 1298 } 1299 1300 override 1301 protected void _setInt(int index, int value) { 1302 Component c = findComponent0(index); 1303 if (index + 4 <= c.endOffset) { 1304 c.buf.setInt(c.idx(index), value); 1305 } else if (order() == ByteOrder.BigEndian) { 1306 _setShort(index, cast(short) (value >>> 16)); 1307 _setShort(index + 2, cast(short) value); 1308 } else { 1309 _setShort(index, cast(short) value); 1310 _setShort(index + 2, cast(short) (value >>> 16)); 1311 } 1312 } 1313 1314 override 1315 protected void _setIntLE(int index, int value) { 1316 Component c = findComponent0(index); 1317 if (index + 4 <= c.endOffset) { 1318 c.buf.setIntLE(c.idx(index), value); 1319 } else if (order() == ByteOrder.BigEndian) { 1320 _setShortLE(index, cast(short) value); 1321 _setShortLE(index + 2, cast(short) (value >>> 16)); 1322 } else { 1323 _setShortLE(index, cast(short) (value >>> 16)); 1324 _setShortLE(index + 2, cast(short) value); 1325 } 1326 } 1327 1328 override 1329 CompositeByteBuf setLong(int index, long value) { 1330 checkIndex(index, 8); 1331 _setLong(index, value); 1332 return this; 1333 } 1334 1335 override 1336 protected void _setLong(int index, long value) { 1337 Component c = findComponent0(index); 1338 if (index + 8 <= c.endOffset) { 1339 c.buf.setLong(c.idx(index), value); 1340 } else if (order() == ByteOrder.BigEndian) { 1341 _setInt(index, cast(int) (value >>> 32)); 1342 _setInt(index + 4, cast(int) value); 1343 } else { 1344 _setInt(index, cast(int) value); 1345 _setInt(index + 4, cast(int) (value >>> 32)); 1346 } 1347 } 1348 1349 override 1350 protected void _setLongLE(int index, long value) { 1351 Component c = findComponent0(index); 1352 if (index + 8 <= c.endOffset) { 1353 c.buf.setLongLE(c.idx(index), value); 1354 } else if (order() == ByteOrder.BigEndian) { 1355 _setIntLE(index, cast(int) value); 1356 _setIntLE(index + 4, cast(int) (value >>> 32)); 1357 } else { 1358 _setIntLE(index, cast(int) (value >>> 32)); 1359 _setIntLE(index + 4, cast(int) value); 1360 } 1361 } 1362 1363 override 1364 CompositeByteBuf setBytes(int index, byte[] src, int srcIndex, int length) { 1365 checkSrcIndex(index, length, srcIndex, cast(int)src.length); 1366 if (length == 0) { 1367 return this; 1368 } 1369 1370 int i = toComponentIndex0(index); 1371 while (length > 0) { 1372 Component c = components[i]; 1373 int localLength = min(length, c.endOffset - index); 1374 c.buf.setBytes(c.idx(index), src, srcIndex, localLength); 1375 index += localLength; 1376 srcIndex += localLength; 1377 length -= localLength; 1378 i ++; 1379 } 1380 return this; 1381 } 1382 1383 override 1384 CompositeByteBuf setBytes(int index, ByteBuffer src) { 1385 int limit = src.limit(); 1386 int length = src.remaining(); 1387 1388 checkIndex(index, length); 1389 if (length == 0) { 1390 return this; 1391 } 1392 1393 int i = toComponentIndex0(index); 1394 try { 1395 while (length > 0) { 1396 Component c = components[i]; 1397 int localLength = min(length, c.endOffset - index); 1398 src.limit(src.position() + localLength); 1399 c.buf.setBytes(c.idx(index), src); 1400 index += localLength; 1401 length -= localLength; 1402 i ++; 1403 } 1404 } finally { 1405 src.limit(limit); 1406 } 1407 return this; 1408 } 1409 1410 override 1411 CompositeByteBuf setBytes(int index, ByteBuf src, int srcIndex, int length) { 1412 checkSrcIndex(index, length, srcIndex, src.capacity()); 1413 if (length == 0) { 1414 return this; 1415 } 1416 1417 int i = toComponentIndex0(index); 1418 while (length > 0) { 1419 Component c = components[i]; 1420 int localLength = min(length, c.endOffset - index); 1421 c.buf.setBytes(c.idx(index), src, srcIndex, localLength); 1422 index += localLength; 1423 srcIndex += localLength; 1424 length -= localLength; 1425 i ++; 1426 } 1427 return this; 1428 } 1429 1430 override 1431 int setBytes(int index, InputStream input, int length) { 1432 checkIndex(index, length); 1433 if (length == 0) { 1434 return input.read([]); 1435 } 1436 1437 int i = toComponentIndex0(index); 1438 int readBytes = 0; 1439 do { 1440 Component c = components[i]; 1441 int localLength = min(length, c.endOffset - index); 1442 if (localLength == 0) { 1443 // Skip empty buffer 1444 i++; 1445 continue; 1446 } 1447 int localReadBytes = c.buf.setBytes(c.idx(index), input, localLength); 1448 if (localReadBytes < 0) { 1449 if (readBytes == 0) { 1450 return -1; 1451 } else { 1452 break; 1453 } 1454 } 1455 1456 index += localReadBytes; 1457 length -= localReadBytes; 1458 readBytes += localReadBytes; 1459 if (localReadBytes == localLength) { 1460 i ++; 1461 } 1462 } while (length > 0); 1463 1464 return readBytes; 1465 } 1466 1467 // override 1468 // int setBytes(int index, ScatteringByteChannel input, int length) { 1469 // checkIndex(index, length); 1470 // if (length == 0) { 1471 // return input.read(EMPTY_NIO_BUFFER); 1472 // } 1473 1474 // int i = toComponentIndex0(index); 1475 // int readBytes = 0; 1476 // do { 1477 // Component c = components[i]; 1478 // int localLength = min(length, c.endOffset - index); 1479 // if (localLength == 0) { 1480 // // Skip empty buffer 1481 // i++; 1482 // continue; 1483 // } 1484 // int localReadBytes = c.buf.setBytes(c.idx(index), input, localLength); 1485 1486 // if (localReadBytes == 0) { 1487 // break; 1488 // } 1489 1490 // if (localReadBytes < 0) { 1491 // if (readBytes == 0) { 1492 // return -1; 1493 // } else { 1494 // break; 1495 // } 1496 // } 1497 1498 // index += localReadBytes; 1499 // length -= localReadBytes; 1500 // readBytes += localReadBytes; 1501 // if (localReadBytes == localLength) { 1502 // i ++; 1503 // } 1504 // } while (length > 0); 1505 1506 // return readBytes; 1507 // } 1508 1509 // override 1510 // int setBytes(int index, FileChannel input, long position, int length) { 1511 // checkIndex(index, length); 1512 // if (length == 0) { 1513 // return input.read(EMPTY_NIO_BUFFER, position); 1514 // } 1515 1516 // int i = toComponentIndex0(index); 1517 // int readBytes = 0; 1518 // do { 1519 // Component c = components[i]; 1520 // int localLength = min(length, c.endOffset - index); 1521 // if (localLength == 0) { 1522 // // Skip empty buffer 1523 // i++; 1524 // continue; 1525 // } 1526 // int localReadBytes = c.buf.setBytes(c.idx(index), input, position + readBytes, localLength); 1527 1528 // if (localReadBytes == 0) { 1529 // break; 1530 // } 1531 1532 // if (localReadBytes < 0) { 1533 // if (readBytes == 0) { 1534 // return -1; 1535 // } else { 1536 // break; 1537 // } 1538 // } 1539 1540 // index += localReadBytes; 1541 // length -= localReadBytes; 1542 // readBytes += localReadBytes; 1543 // if (localReadBytes == localLength) { 1544 // i ++; 1545 // } 1546 // } while (length > 0); 1547 1548 // return readBytes; 1549 // } 1550 1551 override 1552 ByteBuf copy(int index, int length) { 1553 checkIndex(index, length); 1554 ByteBuf dst = allocBuffer(length); 1555 if (length != 0) { 1556 copyTo(index, length, toComponentIndex0(index), dst); 1557 } 1558 return dst; 1559 } 1560 1561 private void copyTo(int index, int length, int componentId, ByteBuf dst) { 1562 int dstIndex = 0; 1563 int i = componentId; 1564 1565 while (length > 0) { 1566 Component c = components[i]; 1567 int localLength = min(length, c.endOffset - index); 1568 c.buf.getBytes(c.idx(index), dst, dstIndex, localLength); 1569 index += localLength; 1570 dstIndex += localLength; 1571 length -= localLength; 1572 i ++; 1573 } 1574 1575 dst.writerIndex(dst.capacity()); 1576 } 1577 1578 /** 1579 * Return the {@link ByteBuf} on the specified index 1580 * 1581 * @param cIndex the index for which the {@link ByteBuf} should be returned 1582 * @return buf the {@link ByteBuf} on the specified index 1583 */ 1584 ByteBuf component(int cIndex) { 1585 checkComponentIndex(cIndex); 1586 return components[cIndex].duplicate(); 1587 } 1588 1589 /** 1590 * Return the {@link ByteBuf} on the specified index 1591 * 1592 * @param offset the offset for which the {@link ByteBuf} should be returned 1593 * @return the {@link ByteBuf} on the specified index 1594 */ 1595 ByteBuf componentAtOffset(int offset) { 1596 return findComponent(offset).duplicate(); 1597 } 1598 1599 /** 1600 * Return the internal {@link ByteBuf} on the specified index. Note that updating the indexes of the returned 1601 * buffer will lead to an undefined behavior of this buffer. 1602 * 1603 * @param cIndex the index for which the {@link ByteBuf} should be returned 1604 */ 1605 ByteBuf internalComponent(int cIndex) { 1606 checkComponentIndex(cIndex); 1607 return components[cIndex].slice(); 1608 } 1609 1610 /** 1611 * Return the internal {@link ByteBuf} on the specified offset. Note that updating the indexes of the returned 1612 * buffer will lead to an undefined behavior of this buffer. 1613 * 1614 * @param offset the offset for which the {@link ByteBuf} should be returned 1615 */ 1616 ByteBuf internalComponentAtOffset(int offset) { 1617 return findComponent(offset).slice(); 1618 } 1619 1620 // weak cache - check it first when looking for component 1621 private Component lastAccessed; 1622 1623 private Component findComponent(int offset) { 1624 Component la = lastAccessed; 1625 if (la !is null && offset >= la.offset && offset < la.endOffset) { 1626 ensureAccessible(); 1627 return la; 1628 } 1629 checkIndex(offset); 1630 return findIt(offset); 1631 } 1632 1633 private Component findComponent0(int offset) { 1634 Component la = lastAccessed; 1635 if (la !is null && offset >= la.offset && offset < la.endOffset) { 1636 return la; 1637 } 1638 return findIt(offset); 1639 } 1640 1641 private Component findIt(int offset) { 1642 for (int low = 0, high = componentCount; low <= high;) { 1643 int mid = low + high >>> 1; 1644 Component c = components[mid]; 1645 if (offset >= c.endOffset) { 1646 low = mid + 1; 1647 } else if (offset < c.offset) { 1648 high = mid - 1; 1649 } else { 1650 lastAccessed = c; 1651 return c; 1652 } 1653 } 1654 1655 throw new Error("should not reach here"); 1656 } 1657 1658 override 1659 int nioBufferCount() { 1660 int size = componentCount; 1661 switch (size) { 1662 case 0: 1663 return 1; 1664 case 1: 1665 return components[0].buf.nioBufferCount(); 1666 default: 1667 int count = 0; 1668 for (int i = 0; i < size; i++) { 1669 count += components[i].buf.nioBufferCount(); 1670 } 1671 return count; 1672 } 1673 } 1674 1675 override 1676 ByteBuffer internalNioBuffer(int index, int length) { 1677 switch (componentCount) { 1678 case 0: 1679 return EMPTY_NIO_BUFFER; 1680 case 1: 1681 return components[0].internalNioBuffer(index, length); 1682 default: 1683 throw new UnsupportedOperationException(); 1684 } 1685 } 1686 1687 override 1688 ByteBuffer nioBuffer(int index, int length) { 1689 checkIndex(index, length); 1690 1691 switch (componentCount) { 1692 case 0: 1693 return EMPTY_NIO_BUFFER; 1694 case 1: 1695 Component c = components[0]; 1696 ByteBuf buf = c.buf; 1697 if (buf.nioBufferCount() == 1) { 1698 return buf.nioBuffer(c.idx(index), length); 1699 } 1700 break; 1701 default : 1702 break; 1703 } 1704 1705 ByteBuffer[] buffers = nioBuffers(index, length); 1706 1707 if (buffers.length == 1) { 1708 return buffers[0]; 1709 } 1710 1711 ByteBuffer merged = BufferUtils.allocate(length).order(order()); 1712 foreach(ByteBuffer buf; buffers) { 1713 merged.put(buf); 1714 } 1715 1716 merged.flip(); 1717 return merged; 1718 } 1719 1720 override 1721 ByteBuffer[] nioBuffers(int index, int length) { 1722 checkIndex(index, length); 1723 if (length == 0) { 1724 return [ EMPTY_NIO_BUFFER ]; 1725 } 1726 1727 implementationMissing(false); 1728 return null; 1729 1730 // RecyclableArrayList buffers = RecyclableArrayList.newInstance(componentCount); 1731 // try { 1732 // int i = toComponentIndex0(index); 1733 // while (length > 0) { 1734 // Component c = components[i]; 1735 // ByteBuf s = c.buf; 1736 // int localLength = min(length, c.endOffset - index); 1737 // switch (s.nioBufferCount()) { 1738 // case 0: 1739 // throw new UnsupportedOperationException(); 1740 // case 1: 1741 // buffers.add(s.nioBuffer(c.idx(index), localLength)); 1742 // break; 1743 // default: 1744 // Collections.addAll(buffers, s.nioBuffers(c.idx(index), localLength)); 1745 // } 1746 1747 // index += localLength; 1748 // length -= localLength; 1749 // i ++; 1750 // } 1751 1752 // return buffers.toArray(new ByteBuffer[0]); 1753 // } finally { 1754 // buffers.recycle(); 1755 // } 1756 } 1757 1758 /** 1759 * Consolidate the composed {@link ByteBuf}s 1760 */ 1761 CompositeByteBuf consolidate() { 1762 ensureAccessible(); 1763 int numComponents = componentCount; 1764 if (numComponents <= 1) { 1765 return this; 1766 } 1767 1768 int capacity = components[numComponents - 1].endOffset; 1769 ByteBuf consolidated = allocBuffer(capacity); 1770 1771 for (int i = 0; i < numComponents; i ++) { 1772 components[i].transferTo(consolidated); 1773 } 1774 lastAccessed = null; 1775 components[0] = new Component(consolidated, 0, 0, capacity, consolidated); 1776 removeCompRange(1, numComponents); 1777 return this; 1778 } 1779 1780 /** 1781 * Consolidate the composed {@link ByteBuf}s 1782 * 1783 * @param cIndex the index on which to start to compose 1784 * @param numComponents the number of components to compose 1785 */ 1786 CompositeByteBuf consolidate(int cIndex, int numComponents) { 1787 checkComponentIndex(cIndex, numComponents); 1788 if (numComponents <= 1) { 1789 return this; 1790 } 1791 1792 int endCIndex = cIndex + numComponents; 1793 Component last = components[endCIndex - 1]; 1794 int capacity = last.endOffset - components[cIndex].offset; 1795 ByteBuf consolidated = allocBuffer(capacity); 1796 1797 for (int i = cIndex; i < endCIndex; i ++) { 1798 components[i].transferTo(consolidated); 1799 } 1800 lastAccessed = null; 1801 removeCompRange(cIndex + 1, endCIndex); 1802 components[cIndex] = new Component(consolidated, 0, 0, capacity, consolidated); 1803 updateComponentOffsets(cIndex); 1804 return this; 1805 } 1806 1807 /** 1808 * Discard all {@link ByteBuf}s which are read. 1809 */ 1810 CompositeByteBuf discardReadComponents() { 1811 ensureAccessible(); 1812 int rIndex = readerIndex(); 1813 if (rIndex == 0) { 1814 return this; 1815 } 1816 1817 // Discard everything if (readerIndex = writerIndex = capacity). 1818 int wIndex = writerIndex(); 1819 if (rIndex == wIndex && wIndex == capacity()) { 1820 for (int i = 0, size = componentCount; i < size; i++) { 1821 components[i].free(); 1822 } 1823 lastAccessed = null; 1824 clearComps(); 1825 setIndex(0, 0); 1826 adjustMarkers(rIndex); 1827 return this; 1828 } 1829 1830 // Remove read components. 1831 int firstComponentId = 0; 1832 Component c = null; 1833 for (int size = componentCount; firstComponentId < size; firstComponentId++) { 1834 c = components[firstComponentId]; 1835 if (c.endOffset > rIndex) { 1836 break; 1837 } 1838 c.free(); 1839 } 1840 if (firstComponentId == 0) { 1841 return this; // Nothing to discard 1842 } 1843 Component la = lastAccessed; 1844 if (la !is null && la.endOffset <= rIndex) { 1845 lastAccessed = null; 1846 } 1847 removeCompRange(0, firstComponentId); 1848 1849 // Update indexes and markers. 1850 int offset = c.offset; 1851 updateComponentOffsets(0); 1852 setIndex(rIndex - offset, wIndex - offset); 1853 adjustMarkers(offset); 1854 return this; 1855 } 1856 1857 override 1858 CompositeByteBuf discardReadBytes() { 1859 ensureAccessible(); 1860 int rIndex = readerIndex(); 1861 if (rIndex == 0) { 1862 return this; 1863 } 1864 1865 // Discard everything if (readerIndex = writerIndex = capacity). 1866 int wIndex = writerIndex(); 1867 if (rIndex == wIndex && wIndex == capacity()) { 1868 for (int i = 0, size = componentCount; i < size; i++) { 1869 components[i].free(); 1870 } 1871 lastAccessed = null; 1872 clearComps(); 1873 setIndex(0, 0); 1874 adjustMarkers(rIndex); 1875 return this; 1876 } 1877 1878 int firstComponentId = 0; 1879 Component c = null; 1880 for (int size = componentCount; firstComponentId < size; firstComponentId++) { 1881 c = components[firstComponentId]; 1882 if (c.endOffset > rIndex) { 1883 break; 1884 } 1885 c.free(); 1886 } 1887 1888 // Replace the first readable component with a new slice. 1889 int trimmedBytes = rIndex - c.offset; 1890 c.offset = 0; 1891 c.endOffset -= rIndex; 1892 c.adjustment += rIndex; 1893 ByteBuf slice = c.slice; 1894 if (slice !is null) { 1895 // We must replace the cached slice with a derived one to ensure that 1896 // it can later be released properly in the case of PooledSlicedByteBuf. 1897 c._slice = slice.slice(trimmedBytes, c.length()); 1898 } 1899 Component la = lastAccessed; 1900 if (la !is null && la.endOffset <= rIndex) { 1901 lastAccessed = null; 1902 } 1903 1904 removeCompRange(0, firstComponentId); 1905 1906 // Update indexes and markers. 1907 updateComponentOffsets(0); 1908 setIndex(0, wIndex - rIndex); 1909 adjustMarkers(rIndex); 1910 return this; 1911 } 1912 1913 private ByteBuf allocBuffer(int capacity) { 1914 return direct ? alloc().directBuffer(capacity) : alloc().heapBuffer(capacity); 1915 } 1916 1917 override 1918 string toString() { 1919 string result = super.toString(); 1920 result = result[0 .. $ - 1]; 1921 return result ~ ", components=" ~ componentCount.to!string() ~ ")"; 1922 } 1923 1924 1925 override 1926 CompositeByteBuf readerIndex(int index) { 1927 super.readerIndex(index); 1928 return this; 1929 } 1930 1931 alias readerIndex = ByteBuf.readerIndex; 1932 1933 override 1934 CompositeByteBuf writerIndex(int index) { 1935 super.writerIndex(index); 1936 return this; 1937 } 1938 alias writerIndex = ByteBuf.writerIndex; 1939 1940 override 1941 CompositeByteBuf setIndex(int rIndex, int wIndex) { 1942 super.setIndex(rIndex, wIndex); 1943 return this; 1944 } 1945 1946 override 1947 CompositeByteBuf clear() { 1948 super.clear(); 1949 return this; 1950 } 1951 1952 override 1953 CompositeByteBuf markReaderIndex() { 1954 super.markReaderIndex(); 1955 return this; 1956 } 1957 1958 override 1959 CompositeByteBuf resetReaderIndex() { 1960 super.resetReaderIndex(); 1961 return this; 1962 } 1963 1964 override 1965 CompositeByteBuf markWriterIndex() { 1966 super.markWriterIndex(); 1967 return this; 1968 } 1969 1970 override 1971 CompositeByteBuf resetWriterIndex() { 1972 super.resetWriterIndex(); 1973 return this; 1974 } 1975 1976 override 1977 CompositeByteBuf ensureWritable(int minWritableBytes) { 1978 super.ensureWritable(minWritableBytes); 1979 return this; 1980 } 1981 1982 override 1983 CompositeByteBuf getBytes(int index, ByteBuf dst) { 1984 return getBytes(index, dst, dst.writableBytes()); 1985 } 1986 1987 override 1988 CompositeByteBuf getBytes(int index, ByteBuf dst, int length) { 1989 getBytes(index, dst, dst.writerIndex(), length); 1990 dst.writerIndex(dst.writerIndex() + length); 1991 return this; 1992 } 1993 1994 override 1995 CompositeByteBuf getBytes(int index, byte[] dst) { 1996 return getBytes(index, dst, 0, cast(int)dst.length); 1997 } 1998 1999 override 2000 CompositeByteBuf setBoolean(int index, bool value) { 2001 return setByte(index, value? 1 : 0); 2002 } 2003 2004 override 2005 CompositeByteBuf setChar(int index, int value) { 2006 return setShort(index, value); 2007 } 2008 2009 override 2010 CompositeByteBuf setFloat(int index, float value) { 2011 return setInt(index, Float.floatToRawIntBits(value)); 2012 } 2013 2014 override 2015 CompositeByteBuf setDouble(int index, double value) { 2016 return setLong(index, Double.doubleToRawLongBits(value)); 2017 } 2018 2019 override 2020 CompositeByteBuf setBytes(int index, ByteBuf src) { 2021 super.setBytes(index, src, src.readableBytes()); 2022 return this; 2023 } 2024 2025 override 2026 CompositeByteBuf setBytes(int index, ByteBuf src, int length) { 2027 super.setBytes(index, src, length); 2028 return this; 2029 } 2030 2031 override 2032 CompositeByteBuf setBytes(int index, byte[] src) { 2033 return setBytes(index, src, 0, cast(int)src.length); 2034 } 2035 2036 override 2037 CompositeByteBuf setZero(int index, int length) { 2038 super.setZero(index, length); 2039 return this; 2040 } 2041 2042 override 2043 CompositeByteBuf readBytes(ByteBuf dst) { 2044 super.readBytes(dst, dst.writableBytes()); 2045 return this; 2046 } 2047 2048 override 2049 CompositeByteBuf readBytes(ByteBuf dst, int length) { 2050 super.readBytes(dst, length); 2051 return this; 2052 } 2053 2054 override 2055 CompositeByteBuf readBytes(ByteBuf dst, int dstIndex, int length) { 2056 super.readBytes(dst, dstIndex, length); 2057 return this; 2058 } 2059 2060 override 2061 CompositeByteBuf readBytes(byte[] dst) { 2062 super.readBytes(dst, 0, cast(int)dst.length); 2063 return this; 2064 } 2065 2066 override 2067 CompositeByteBuf readBytes(byte[] dst, int dstIndex, int length) { 2068 super.readBytes(dst, dstIndex, length); 2069 return this; 2070 } 2071 2072 override 2073 CompositeByteBuf readBytes(ByteBuffer dst) { 2074 super.readBytes(dst); 2075 return this; 2076 } 2077 2078 override 2079 CompositeByteBuf readBytes(OutputStream output, int length) { 2080 super.readBytes(output, length); 2081 return this; 2082 } 2083 2084 override 2085 CompositeByteBuf skipBytes(int length) { 2086 super.skipBytes(length); 2087 return this; 2088 } 2089 2090 override 2091 CompositeByteBuf writeBoolean(bool value) { 2092 writeByte(value ? 1 : 0); 2093 return this; 2094 } 2095 2096 override 2097 CompositeByteBuf writeByte(int value) { 2098 ensureWritable0(1); 2099 _setByte(_writerIndex++, value); 2100 return this; 2101 } 2102 2103 override 2104 CompositeByteBuf writeShort(int value) { 2105 super.writeShort(value); 2106 return this; 2107 } 2108 2109 override 2110 CompositeByteBuf writeMedium(int value) { 2111 super.writeMedium(value); 2112 return this; 2113 } 2114 2115 override 2116 CompositeByteBuf writeInt(int value) { 2117 super.writeInt(value); 2118 return this; 2119 } 2120 2121 override 2122 CompositeByteBuf writeLong(long value) { 2123 super.writeLong(value); 2124 return this; 2125 } 2126 2127 override 2128 CompositeByteBuf writeChar(int value) { 2129 super.writeShort(value); 2130 return this; 2131 } 2132 2133 override 2134 CompositeByteBuf writeFloat(float value) { 2135 super.writeInt(Float.floatToRawIntBits(value)); 2136 return this; 2137 } 2138 2139 override 2140 CompositeByteBuf writeDouble(double value) { 2141 super.writeLong(Double.doubleToRawLongBits(value)); 2142 return this; 2143 } 2144 2145 override 2146 CompositeByteBuf writeBytes(ByteBuf src) { 2147 super.writeBytes(src, src.readableBytes()); 2148 return this; 2149 } 2150 2151 override 2152 CompositeByteBuf writeBytes(ByteBuf src, int length) { 2153 super.writeBytes(src, length); 2154 return this; 2155 } 2156 2157 override 2158 CompositeByteBuf writeBytes(ByteBuf src, int srcIndex, int length) { 2159 super.writeBytes(src, srcIndex, length); 2160 return this; 2161 } 2162 2163 override 2164 CompositeByteBuf writeBytes(byte[] src) { 2165 super.writeBytes(src, 0, cast(int)src.length); 2166 return this; 2167 } 2168 2169 override 2170 CompositeByteBuf writeBytes(byte[] src, int srcIndex, int length) { 2171 super.writeBytes(src, srcIndex, length); 2172 return this; 2173 } 2174 2175 override 2176 CompositeByteBuf writeBytes(ByteBuffer src) { 2177 super.writeBytes(src); 2178 return this; 2179 } 2180 2181 override 2182 CompositeByteBuf writeZero(int length) { 2183 super.writeZero(length); 2184 return this; 2185 } 2186 2187 override 2188 CompositeByteBuf retain(int increment) { 2189 super.retain(increment); 2190 return this; 2191 } 2192 2193 override 2194 CompositeByteBuf retain() { 2195 super.retain(); 2196 return this; 2197 } 2198 2199 override 2200 CompositeByteBuf touch() { 2201 return this; 2202 } 2203 2204 override 2205 CompositeByteBuf touch(Object hint) { 2206 return this; 2207 } 2208 2209 override 2210 ByteBuffer[] nioBuffers() { 2211 return nioBuffers(readerIndex(), readableBytes()); 2212 } 2213 2214 override 2215 CompositeByteBuf discardSomeReadBytes() { 2216 return discardReadComponents(); 2217 } 2218 2219 override 2220 protected void deallocate() { 2221 if (freed) { 2222 return; 2223 } 2224 2225 freed = true; 2226 // We're not using foreach to avoid creating an iterator. 2227 // see https://github.com/netty/netty/issues/2642 2228 for (int i = 0, size = componentCount; i < size; i++) { 2229 components[i].free(); 2230 } 2231 } 2232 2233 override 2234 bool isAccessible() { 2235 return !freed; 2236 } 2237 2238 override 2239 ByteBuf unwrap() { 2240 return null; 2241 } 2242 2243 // private final class CompositeByteBufIterator : InputRange!(ByteBuf) { 2244 // private int size = numComponents(); 2245 // private int index; 2246 2247 // override 2248 // bool hasNext() { 2249 // return size > index; 2250 // } 2251 2252 // override 2253 // ByteBuf next() { 2254 // if (size != numComponents()) { 2255 // throw new ConcurrentModificationException(); 2256 // } 2257 // if (!hasNext()) { 2258 // throw new NoSuchElementException(); 2259 // } 2260 // try { 2261 // return components[index++].slice(); 2262 // } catch (IndexOutOfBoundsException e) { 2263 // throw new ConcurrentModificationException(); 2264 // } 2265 // } 2266 2267 // override 2268 // void remove() { 2269 // throw new UnsupportedOperationException("Read-Only"); 2270 // } 2271 // } 2272 2273 // Component array manipulation - range checking omitted 2274 2275 private void clearComps() { 2276 removeCompRange(0, componentCount); 2277 } 2278 2279 private void removeComp(int i) { 2280 removeCompRange(i, i + 1); 2281 } 2282 2283 private void removeCompRange(int from, int to) { 2284 if (from >= to) { 2285 return; 2286 } 2287 int size = componentCount; 2288 assert(from >= 0 && to <= size); 2289 if (to < size) { 2290 // System.arraycopy(components, to, components, from, size - to); 2291 // components[from .. from + size - to] = components[to .. size]; 2292 for(int i=0; i<size - to; i++) { 2293 components[from+i] = components[to+i]; 2294 } 2295 } 2296 int newSize = size - to + from; 2297 for (int i = newSize; i < size; i++) { 2298 components[i] = null; 2299 } 2300 componentCount = newSize; 2301 } 2302 2303 private void addComp(int i, Component c) { 2304 shiftComps(i, 1); 2305 components[i] = c; 2306 } 2307 2308 private void shiftComps(int i, int count) { 2309 int size = componentCount, newSize = size + count; 2310 assert( i >= 0 && i <= size && count > 0); 2311 if (newSize > components.length) { 2312 // grow the array 2313 int newArrSize = max(size + (size >> 1), newSize); 2314 Component[] newArr; 2315 if (i == size) { 2316 // Arrays.copyOf(components, newArrSize, Component[].class); 2317 newArr = components ~ cast(Component)null ; 2318 } else { 2319 newArr = new Component[newArrSize]; 2320 if (i > 0) { 2321 // System.arraycopy(components, 0, newArr, 0, i); 2322 newArr[0..i] = components[0..i]; 2323 } 2324 if (i < size) { 2325 newArr[i + count .. size+count] = components[i .. size]; 2326 // System.arraycopy(components, i, newArr, i + count, size - i); 2327 } 2328 } 2329 components = newArr; 2330 } else if (i < size) { 2331 // System.arraycopy(components, i, components, i + count, size - i); 2332 // components[i + count .. count+size] = components[i .. size]; 2333 for(int j=0; j<size - i; j++) 2334 components[i + count + j] = components[i+j]; 2335 } 2336 componentCount = newSize; 2337 } 2338 } 2339 2340 2341 private final class Component { 2342 ByteBuf buf; 2343 int adjustment; 2344 int offset; 2345 int endOffset; 2346 2347 private ByteBuf _slice; // cached slice, may be null 2348 2349 this(ByteBuf buf, int srcOffset, int offset, int len, ByteBuf slice) { 2350 this.buf = buf; 2351 this.offset = offset; 2352 this.endOffset = offset + len; 2353 this.adjustment = srcOffset - offset; 2354 this._slice = slice; 2355 } 2356 2357 int idx(int index) { 2358 return index + adjustment; 2359 } 2360 2361 int length() { 2362 return endOffset - offset; 2363 } 2364 2365 void reposition(int newOffset) { 2366 int move = newOffset - offset; 2367 endOffset += move; 2368 adjustment -= move; 2369 offset = newOffset; 2370 } 2371 2372 // copy then release 2373 void transferTo(ByteBuf dst) { 2374 dst.writeBytes(buf, idx(offset), length()); 2375 free(); 2376 } 2377 2378 ByteBuf slice() { 2379 return _slice !is null ? _slice : (_slice = buf.slice(idx(offset), length())); 2380 } 2381 2382 ByteBuf duplicate() { 2383 return buf.duplicate().setIndex(idx(offset), idx(endOffset)); 2384 } 2385 2386 ByteBuffer internalNioBuffer(int index, int length) { 2387 // We must not return the unwrapped buffer's internal buffer 2388 // if it was originally added as a slice - this check of the 2389 // slice field is threadsafe since we only care whether it 2390 // was set upon Component construction, and we aren't 2391 // attempting to access the referenced slice itself 2392 return _slice !is null ? buf.nioBuffer(idx(index), length) 2393 : buf.internalNioBuffer(idx(index), length); 2394 } 2395 2396 void free() { 2397 // Release the slice if present since it may have a different 2398 // refcount to the unwrapped buf if it is a PooledSlicedByteBuf 2399 ByteBuf buffer = _slice; 2400 if (buffer !is null) { 2401 buffer.release(); 2402 } else { 2403 buf.release(); 2404 } 2405 // null out in either case since it could be racy if set lazily (but not 2406 // in the case we care about, where it will have been set in the ctor) 2407 _slice = null; 2408 } 2409 } 2410 2411 2412 2413 // support passing arrays of other types instead of having to copy to a ByteBuf[] first 2414 interface ByteWrapper(T) { 2415 ByteBuf wrap(T bytes); 2416 bool isEmpty(T bytes); 2417 }