Merge pull request #11 from netty/byte-cursor
Turn ByteIterator into ByteCursor
This commit is contained in:
commit
deeea157c0
@ -295,69 +295,70 @@ public interface Buf extends Rc<Buf>, BufAccessors {
|
||||
}
|
||||
|
||||
/**
|
||||
* Iterate the readable bytes of this buffer. The {@linkplain #readerOffset() reader offset} and
|
||||
* {@linkplain #writerOffset() witer offset} are not modified by the iterator.
|
||||
* Open a cursor to iterate the readable bytes of this buffer. The {@linkplain #readerOffset() reader offset} and
|
||||
* {@linkplain #writerOffset() witer offset} are not modified by the cursor.
|
||||
* <p>
|
||||
* Care should be taken to ensure that the buffers lifetime extends beyond the iteration, and the
|
||||
* {@linkplain #readerOffset() reader offset} and {@linkplain #writerOffset() writer offset} are not modified while
|
||||
* the iteration takes place. Otherwise unpredictable behaviour might result.
|
||||
* Care should be taken to ensure that the buffers lifetime extends beyond the cursor and the iteration, and that
|
||||
* the {@linkplain #readerOffset() reader offset} and {@linkplain #writerOffset() writer offset} are not modified
|
||||
* while the iteration takes place. Otherwise unpredictable behaviour might result.
|
||||
*
|
||||
* @return A {@link ByteIterator} for the readable bytes of this buffer.
|
||||
* @return A {@link ByteCursor} for iterating the readable bytes of this buffer.
|
||||
*/
|
||||
default ByteIterator iterate() {
|
||||
return iterate(readerOffset(), readableBytes());
|
||||
default ByteCursor openCursor() {
|
||||
return openCursor(readerOffset(), readableBytes());
|
||||
}
|
||||
|
||||
/**
|
||||
* Iterate the given number bytes of this buffer, starting at the given offset.
|
||||
* Open a cursor to iterate the given number bytes of this buffer, starting at the given offset.
|
||||
* The {@linkplain #readerOffset() reader offset} and {@linkplain #writerOffset() witer offset} are not modified by
|
||||
* the iterator.
|
||||
* the cursor.
|
||||
* <p>
|
||||
* Care should be taken to ensure that the buffers lifetime extends beyond the iteration, and the
|
||||
* {@linkplain #readerOffset() reader offset} and {@linkplain #writerOffset() writer offset} are not modified while
|
||||
* the iteration takes place. Otherwise unpredictable behaviour might result.
|
||||
* Care should be taken to ensure that the buffers lifetime extends beyond the cursor and the iteration, and that
|
||||
* the {@linkplain #readerOffset() reader offset} and {@linkplain #writerOffset() writer offset} are not modified
|
||||
* while the iteration takes place. Otherwise unpredictable behaviour might result.
|
||||
*
|
||||
* @param fromOffset The offset into the buffer where iteration should start.
|
||||
* The first byte read from the iterator will be the byte at this offset.
|
||||
* @param length The number of bytes to iterate.
|
||||
* @return A {@link ByteIterator} for the given stretch of bytes of this buffer.
|
||||
* @return A {@link ByteCursor} for the given stretch of bytes of this buffer.
|
||||
* @throws IllegalArgumentException if the length is negative, or if the region given by the {@code fromOffset} and
|
||||
* the {@code length} reaches outside of the bounds of this buffer.
|
||||
*/
|
||||
ByteIterator iterate(int fromOffset, int length);
|
||||
ByteCursor openCursor(int fromOffset, int length);
|
||||
|
||||
/**
|
||||
* Iterate the readable bytes of this buffer, in reverse. The {@linkplain #readerOffset() reader offset} and
|
||||
* {@linkplain #writerOffset() witer offset} are not modified by the iterator.
|
||||
* Open a cursor to iterate the readable bytes of this buffer, in reverse.
|
||||
* The {@linkplain #readerOffset() reader offset} and {@linkplain #writerOffset() witer offset} are not modified by
|
||||
* the cursor.
|
||||
* <p>
|
||||
* Care should be taken to ensure that the buffers lifetime extends beyond the iteration, and the
|
||||
* {@linkplain #readerOffset() reader offset} and {@linkplain #writerOffset() writer offset} are not modified while
|
||||
* the iteration takes place. Otherwise unpredictable behaviour might result.
|
||||
* Care should be taken to ensure that the buffers lifetime extends beyond the cursor and the iteration, and that
|
||||
* the {@linkplain #readerOffset() reader offset} and {@linkplain #writerOffset() writer offset} are not modified
|
||||
* while the iteration takes place. Otherwise unpredictable behaviour might result.
|
||||
*
|
||||
* @return A {@link ByteIterator} for the readable bytes of this buffer.
|
||||
* @return A {@link ByteCursor} for the readable bytes of this buffer.
|
||||
*/
|
||||
default ByteIterator iterateReverse() {
|
||||
default ByteCursor openReverseCursor() {
|
||||
int woff = writerOffset();
|
||||
return iterateReverse(woff == 0? 0 : woff - 1, readableBytes());
|
||||
return openReverseCursor(woff == 0? 0 : woff - 1, readableBytes());
|
||||
}
|
||||
|
||||
/**
|
||||
* Iterate the given number bytes of this buffer, in reverse, starting at the given offset.
|
||||
* Open a cursor to iterate the given number bytes of this buffer, in reverse, starting at the given offset.
|
||||
* The {@linkplain #readerOffset() reader offset} and {@linkplain #writerOffset() witer offset} are not modified by
|
||||
* the iterator.
|
||||
* the cursor.
|
||||
* <p>
|
||||
* Care should be taken to ensure that the buffers lifetime extends beyond the iteration, and the
|
||||
* {@linkplain #readerOffset() reader offset} and {@linkplain #writerOffset() writer offset} are not modified while
|
||||
* the iteration takes place. Otherwise unpredictable behaviour might result.
|
||||
* Care should be taken to ensure that the buffers lifetime extends beyond the cursor and the iteration, and that
|
||||
* the {@linkplain #readerOffset() reader offset} and {@linkplain #writerOffset() writer offset} are not modified
|
||||
* while the iteration takes place. Otherwise unpredictable behaviour might result.
|
||||
*
|
||||
* @param fromOffset The offset into the buffer where iteration should start.
|
||||
* The first byte read from the iterator will be the byte at this offset.
|
||||
* @param length The number of bytes to iterate.
|
||||
* @return A {@link ByteIterator} for the given stretch of bytes of this buffer.
|
||||
* @return A {@link ByteCursor} for the given stretch of bytes of this buffer.
|
||||
* @throws IllegalArgumentException if the length is negative, or if the region given by the {@code fromOffset} and
|
||||
* the {@code length} reaches outside of the bounds of this buffer.
|
||||
*/
|
||||
ByteIterator iterateReverse(int fromOffset, int length);
|
||||
ByteCursor openReverseCursor(int fromOffset, int length);
|
||||
|
||||
/**
|
||||
* Ensure that this buffer has {@linkplain #writableBytes() available space for writing} the given number of
|
||||
|
@ -17,48 +17,57 @@ package io.netty.buffer.api;
|
||||
import io.netty.util.ByteProcessor;
|
||||
|
||||
/**
|
||||
* The ByteIterator scans through a sequence of bytes.
|
||||
* The ByteCursor scans through a sequence of bytes.
|
||||
* This is similar to {@link ByteProcessor}, but for external iteration rather than internal iteration.
|
||||
* The external iteration allows the callers to control the pace of the iteration.
|
||||
* The API includes methods for reading {@code long}s as a batch of 8 bytes.
|
||||
* The long values are always in big-endian format, so that the highest-order byte in the long value, contain the byte
|
||||
* that would otherwise have been returned by the next call to {@link #nextByte()}.
|
||||
* that would otherwise have been returned by the next call to {@link #getByte()}.
|
||||
*/
|
||||
public interface ByteIterator {
|
||||
public interface ByteCursor {
|
||||
/**
|
||||
* Check if the iterator has at least 8 bytes left.
|
||||
* Note that when this method returns {@code false}, the {@link #hasNextByte()} can still return {@code true}.
|
||||
* Check if the iterator has at least 8 bytes left, and if so, read those 8 bytes and move the cursor forward.
|
||||
* The bytes are packed as a {@code long} value in big-endian format, such that the highest-order byte
|
||||
* in the long, is the byte that would otherwise have been returned by the next call to {@link #getByte()},
|
||||
* after a call to {@link #readByte()}.
|
||||
* The bytes (as a {@code long}) will then be available through the {@link #getLong()} method.
|
||||
* <p>
|
||||
* Note that when this method returns {@code false}, the {@link #readByte()} can still return {@code true}.
|
||||
* It is recommended to have any long-processing loop be followed by a byte-processing loop for the 7 or fewer
|
||||
* bytes that might form a tail in the iterator.
|
||||
* bytes that might form a tail in the cursor.
|
||||
* <p>
|
||||
* Also note that this method will not influence what is returned the {@link #getByte()} method.
|
||||
*
|
||||
* @return {@code true} if a call to {@link #nextLong()} would succeed, otherwise {@code false}.
|
||||
* @return {@code true} if the cursor read 8 bytes and moved forward, otherwise {@code false}.
|
||||
*/
|
||||
boolean hasNextLong();
|
||||
boolean readLong();
|
||||
|
||||
/**
|
||||
* Read and return the next 8 bytes, and move the iterator position forward by 8 bytes.
|
||||
* The bytes are packed and return as a {@code long} value in big-endian format, such that the highest-order byte
|
||||
* in the long, is the byte that would otherwise have been returned by the next call to {@link #nextByte()}.
|
||||
* Return the last 8 bytes read by {@link #readLong()}.
|
||||
* If {@link #readLong()} has not been called on this cursor before, then {@code -1} is returned.
|
||||
*
|
||||
* @return The next 8 bytes in big-endian format.
|
||||
* @throws java.util.NoSuchElementException If the iterator has fewer than 8 bytes left.
|
||||
* @return The 8 bytes, in big-endian format, that was read by the most recent successful call to
|
||||
* {@link #readLong()}.
|
||||
*/
|
||||
long nextLong();
|
||||
long getLong();
|
||||
|
||||
/**
|
||||
* Check if the iterator has at least one byte left.
|
||||
* Check if the iterator has at least one byte left, and if so, read that byte and move the cursor forward.
|
||||
* The byte will then be available through the {@link #getByte()}.
|
||||
* <p>
|
||||
* Note that this method will not influence what is returned from the {@link #getLong()} method.
|
||||
*
|
||||
* @return {@code true} if the next call to {@link #nextByte()} would succeed, otherwise {@code false}.
|
||||
* @return {@code true} if the cursor read a byte and moved forward, otherwise {@code false}.
|
||||
*/
|
||||
boolean hasNextByte();
|
||||
boolean readByte();
|
||||
|
||||
/**
|
||||
* Read and return the next byte, and move the iterator position] forward by one byte.
|
||||
* Return the last byte that was read by {@link #readByte()}.
|
||||
* If {@link #readByte()} has not been called on this cursor before, then {@code -1} is returned.
|
||||
*
|
||||
* @return The next byte.
|
||||
* @throws java.util.NoSuchElementException If the iterator has no more bytes left.
|
||||
* @return The next byte that was read by the most recent successful call to {@link #readByte()}.
|
||||
*/
|
||||
byte nextByte();
|
||||
byte getByte();
|
||||
|
||||
/**
|
||||
* The current position of this iterator into the underlying sequence of bytes.
|
||||
@ -85,14 +94,10 @@ public interface ByteIterator {
|
||||
*/
|
||||
default int process(ByteProcessor processor) {
|
||||
boolean requestMore = true;
|
||||
int index = currentOffset();
|
||||
if (hasNextByte()) {
|
||||
byte val = nextByte();
|
||||
while ((requestMore = processor.process(val)) && hasNextByte()) {
|
||||
val = nextByte();
|
||||
index++;
|
||||
int count = 0;
|
||||
while (readByte() && (requestMore = processor.process(getByte()))) {
|
||||
count++;
|
||||
}
|
||||
}
|
||||
return requestMore? -1 : index;
|
||||
return requestMore? -1 : count;
|
||||
}
|
||||
}
|
@ -18,7 +18,6 @@ package io.netty.buffer.api;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.nio.ByteOrder;
|
||||
import java.util.Arrays;
|
||||
import java.util.NoSuchElementException;
|
||||
import java.util.Objects;
|
||||
|
||||
final class CompositeBuf extends RcSupport<Buf, CompositeBuf> implements Buf {
|
||||
@ -293,18 +292,17 @@ final class CompositeBuf extends RcSupport<Buf, CompositeBuf> implements Buf {
|
||||
|
||||
// Iterate in reverse to account for src and dest buffer overlap.
|
||||
// todo optimise by delegating to constituent buffers.
|
||||
var itr = iterateReverse(srcPos + length - 1, length);
|
||||
var cursor = openReverseCursor(srcPos + length - 1, length);
|
||||
ByteOrder prevOrder = dest.order();
|
||||
// We read longs in BE, in reverse, so they need to be flipped for writing.
|
||||
dest.order(ByteOrder.LITTLE_ENDIAN);
|
||||
try {
|
||||
while (itr.hasNextLong()) {
|
||||
long val = itr.nextLong();
|
||||
while (cursor.readLong()) {
|
||||
length -= Long.BYTES;
|
||||
dest.setLong(destPos + length, val);
|
||||
dest.setLong(destPos + length, cursor.getLong());
|
||||
}
|
||||
while (itr.hasNextByte()) {
|
||||
dest.setByte(destPos + --length, itr.nextByte());
|
||||
while (cursor.readByte()) {
|
||||
dest.setByte(destPos + --length, cursor.getByte());
|
||||
}
|
||||
} finally {
|
||||
dest.order(prevOrder);
|
||||
@ -312,7 +310,7 @@ final class CompositeBuf extends RcSupport<Buf, CompositeBuf> implements Buf {
|
||||
}
|
||||
|
||||
@Override
|
||||
public ByteIterator iterate(int fromOffset, int length) {
|
||||
public ByteCursor openCursor(int fromOffset, int length) {
|
||||
if (fromOffset < 0) {
|
||||
throw new IllegalArgumentException("The fromOffset cannot be negative: " + fromOffset + '.');
|
||||
}
|
||||
@ -326,77 +324,94 @@ final class CompositeBuf extends RcSupport<Buf, CompositeBuf> implements Buf {
|
||||
int startBufferIndex = searchOffsets(fromOffset);
|
||||
int off = fromOffset - offsets[startBufferIndex];
|
||||
Buf startBuf = bufs[startBufferIndex];
|
||||
ByteIterator startIterator = startBuf.iterate(off, Math.min(startBuf.capacity() - off, length));
|
||||
return new ByteIterator() {
|
||||
ByteCursor startCursor = startBuf.openCursor(off, Math.min(startBuf.capacity() - off, length));
|
||||
return new ByteCursor() {
|
||||
int index = fromOffset;
|
||||
final int end = fromOffset + length;
|
||||
int bufferIndex = startBufferIndex;
|
||||
ByteIterator itr = startIterator;
|
||||
int initOffset = startCursor.currentOffset();
|
||||
ByteCursor cursor = startCursor;
|
||||
long longValue = -1;
|
||||
byte byteValue = -1;
|
||||
|
||||
@Override
|
||||
public boolean hasNextLong() {
|
||||
return bytesLeft() >= Long.BYTES;
|
||||
public boolean readLong() {
|
||||
if (cursor.readLong()) {
|
||||
longValue = cursor.getLong();
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public long nextLong() {
|
||||
if (itr.hasNextLong()) {
|
||||
long val = itr.nextLong();
|
||||
index += Long.BYTES;
|
||||
return val;
|
||||
if (bytesLeft() >= Long.BYTES) {
|
||||
longValue = nextLongFromBytes();
|
||||
return true;
|
||||
}
|
||||
if (!hasNextLong()) {
|
||||
throw new NoSuchElementException();
|
||||
}
|
||||
return nextLongFromBytes(); // Leave index increments to 'nextByte'
|
||||
return false;
|
||||
}
|
||||
|
||||
private long nextLongFromBytes() {
|
||||
if (cursor.bytesLeft() == 0) {
|
||||
nextCursor();
|
||||
if (cursor.readLong()) {
|
||||
return cursor.getLong();
|
||||
}
|
||||
}
|
||||
long val = 0;
|
||||
for (int i = 0; i < 8; i++) {
|
||||
readByte();
|
||||
val <<= 8;
|
||||
val |= nextByte();
|
||||
val |= getByte();
|
||||
}
|
||||
return val;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasNextByte() {
|
||||
return index < end;
|
||||
public long getLong() {
|
||||
return longValue;
|
||||
}
|
||||
|
||||
@Override
|
||||
public byte nextByte() {
|
||||
if (itr.hasNextByte()) {
|
||||
byte val = itr.nextByte();
|
||||
index++;
|
||||
return val;
|
||||
public boolean readByte() {
|
||||
if (cursor.readByte()) {
|
||||
byteValue = cursor.getByte();
|
||||
return true;
|
||||
}
|
||||
if (!hasNextByte()) {
|
||||
throw new NoSuchElementException();
|
||||
if (bytesLeft() > 0) {
|
||||
nextCursor();
|
||||
cursor.readByte();
|
||||
byteValue = cursor.getByte();
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private void nextCursor() {
|
||||
bufferIndex++;
|
||||
Buf nextBuf = bufs[bufferIndex];
|
||||
itr = nextBuf.iterate(0, Math.min(nextBuf.capacity(), bytesLeft()));
|
||||
byte val = itr.nextByte();
|
||||
index++;
|
||||
return val;
|
||||
cursor = nextBuf.openCursor(0, Math.min(nextBuf.capacity(), bytesLeft()));
|
||||
initOffset = 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public byte getByte() {
|
||||
return byteValue;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int currentOffset() {
|
||||
int currOff = cursor.currentOffset();
|
||||
index += currOff - initOffset;
|
||||
initOffset = currOff;
|
||||
return index;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int bytesLeft() {
|
||||
return end - index;
|
||||
return end - currentOffset();
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@Override
|
||||
public ByteIterator iterateReverse(int fromOffset, int length) {
|
||||
public ByteCursor openReverseCursor(int fromOffset, int length) {
|
||||
if (fromOffset < 0) {
|
||||
throw new IllegalArgumentException("The fromOffset cannot be negative: " + fromOffset + '.');
|
||||
}
|
||||
@ -410,70 +425,90 @@ final class CompositeBuf extends RcSupport<Buf, CompositeBuf> implements Buf {
|
||||
int startBufferIndex = searchOffsets(fromOffset);
|
||||
int off = fromOffset - offsets[startBufferIndex];
|
||||
Buf startBuf = bufs[startBufferIndex];
|
||||
ByteIterator startIterator = startBuf.iterateReverse(off, Math.min(off + 1, length));
|
||||
return new ByteIterator() {
|
||||
ByteCursor startCursor = startBuf.openReverseCursor(off, Math.min(off + 1, length));
|
||||
return new ByteCursor() {
|
||||
int index = fromOffset;
|
||||
final int end = fromOffset - length;
|
||||
int bufferIndex = startBufferIndex;
|
||||
ByteIterator itr = startIterator;
|
||||
int initOffset = startCursor.currentOffset();
|
||||
ByteCursor cursor = startCursor;
|
||||
long longValue = -1;
|
||||
byte byteValue = -1;
|
||||
|
||||
@Override
|
||||
public boolean hasNextLong() {
|
||||
return bytesLeft() >= Long.BYTES;
|
||||
public boolean readLong() {
|
||||
if (cursor.readLong()) {
|
||||
longValue = cursor.getLong();
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public long nextLong() {
|
||||
if (itr.hasNextLong()) {
|
||||
index -= Long.BYTES;
|
||||
return itr.nextLong();
|
||||
if (bytesLeft() >= Long.BYTES) {
|
||||
longValue = nextLongFromBytes();
|
||||
return true;
|
||||
}
|
||||
if (!hasNextLong()) {
|
||||
throw new NoSuchElementException();
|
||||
}
|
||||
return nextLongFromBytes(); // Leave index increments to 'nextByte'
|
||||
return false;
|
||||
}
|
||||
|
||||
private long nextLongFromBytes() {
|
||||
if (cursor.bytesLeft() == 0) {
|
||||
nextCursor();
|
||||
if (cursor.readLong()) {
|
||||
return cursor.getLong();
|
||||
}
|
||||
}
|
||||
long val = 0;
|
||||
for (int i = 0; i < 8; i++) {
|
||||
readByte();
|
||||
val <<= 8;
|
||||
val |= nextByte();
|
||||
val |= getByte();
|
||||
}
|
||||
return val;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasNextByte() {
|
||||
return index > end;
|
||||
public long getLong() {
|
||||
return longValue;
|
||||
}
|
||||
|
||||
@Override
|
||||
public byte nextByte() {
|
||||
if (itr.hasNextByte()) {
|
||||
byte val = itr.nextByte();
|
||||
index--;
|
||||
return val;
|
||||
public boolean readByte() {
|
||||
if (cursor.readByte()) {
|
||||
byteValue = cursor.getByte();
|
||||
return true;
|
||||
}
|
||||
if (!hasNextByte()) {
|
||||
throw new NoSuchElementException();
|
||||
if (bytesLeft() > 0) {
|
||||
nextCursor();
|
||||
cursor.readByte();
|
||||
byteValue = cursor.getByte();
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private void nextCursor() {
|
||||
bufferIndex--;
|
||||
Buf nextBuf = bufs[bufferIndex];
|
||||
itr = nextBuf.iterateReverse(nextBuf.capacity() - 1, Math.min(nextBuf.capacity(), bytesLeft()));
|
||||
byte val = itr.nextByte();
|
||||
index--;
|
||||
return val;
|
||||
int length = Math.min(nextBuf.capacity(), bytesLeft());
|
||||
int offset = nextBuf.capacity() - 1;
|
||||
cursor = nextBuf.openReverseCursor(offset, length);
|
||||
initOffset = offset;
|
||||
}
|
||||
|
||||
@Override
|
||||
public byte getByte() {
|
||||
return byteValue;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int currentOffset() {
|
||||
int currOff = cursor.currentOffset();
|
||||
index -= initOffset - currOff;
|
||||
initOffset = currOff;
|
||||
return index;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int bytesLeft() {
|
||||
return index - end;
|
||||
return currentOffset() - end;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
@ -18,7 +18,7 @@ package io.netty.buffer.api.memseg;
|
||||
import io.netty.buffer.api.Allocator;
|
||||
import io.netty.buffer.api.AllocatorControl;
|
||||
import io.netty.buffer.api.Buf;
|
||||
import io.netty.buffer.api.ByteIterator;
|
||||
import io.netty.buffer.api.ByteCursor;
|
||||
import io.netty.buffer.api.Drop;
|
||||
import io.netty.buffer.api.Owned;
|
||||
import io.netty.buffer.api.RcSupport;
|
||||
@ -26,7 +26,6 @@ import jdk.incubator.foreign.MemorySegment;
|
||||
|
||||
import java.nio.ByteBuffer;
|
||||
import java.nio.ByteOrder;
|
||||
import java.util.NoSuchElementException;
|
||||
|
||||
import static jdk.incubator.foreign.MemoryAccess.getByteAtOffset;
|
||||
import static jdk.incubator.foreign.MemoryAccess.getCharAtOffset;
|
||||
@ -158,18 +157,18 @@ class MemSegBuf extends RcSupport<Buf, MemSegBuf> implements Buf {
|
||||
public void copyInto(int srcPos, Buf dest, int destPos, int length) {
|
||||
// todo optimise: specialise for MemSegBuf.
|
||||
// Iterate in reverse to account for src and dest buffer overlap.
|
||||
var itr = iterateReverse(srcPos + length - 1, length);
|
||||
var itr = openReverseCursor(srcPos + length - 1, length);
|
||||
ByteOrder prevOrder = dest.order();
|
||||
// We read longs in BE, in reverse, so they need to be flipped for writing.
|
||||
dest.order(ByteOrder.LITTLE_ENDIAN);
|
||||
try {
|
||||
while (itr.hasNextLong()) {
|
||||
long val = itr.nextLong();
|
||||
while (itr.readLong()) {
|
||||
long val = itr.getLong();
|
||||
length -= Long.BYTES;
|
||||
dest.setLong(destPos + length, val);
|
||||
}
|
||||
while (itr.hasNextByte()) {
|
||||
dest.setByte(destPos + --length, itr.nextByte());
|
||||
while (itr.readByte()) {
|
||||
dest.setByte(destPos + --length, itr.getByte());
|
||||
}
|
||||
} finally {
|
||||
dest.order(prevOrder);
|
||||
@ -177,7 +176,7 @@ class MemSegBuf extends RcSupport<Buf, MemSegBuf> implements Buf {
|
||||
}
|
||||
|
||||
@Override
|
||||
public ByteIterator iterate(int fromOffset, int length) {
|
||||
public ByteCursor openCursor(int fromOffset, int length) {
|
||||
if (fromOffset < 0) {
|
||||
throw new IllegalArgumentException("The fromOffset cannot be negative: " + fromOffset + '.');
|
||||
}
|
||||
@ -188,39 +187,41 @@ class MemSegBuf extends RcSupport<Buf, MemSegBuf> implements Buf {
|
||||
throw new IllegalArgumentException("The fromOffset+length is beyond the end of the buffer: " +
|
||||
"fromOffset=" + fromOffset + ", length=" + length + '.');
|
||||
}
|
||||
return new ByteIterator() {
|
||||
return new ByteCursor() {
|
||||
final MemorySegment segment = seg;
|
||||
int index = fromOffset;
|
||||
final int end = index + length;
|
||||
long longValue = -1;
|
||||
byte byteValue = -1;
|
||||
|
||||
@Override
|
||||
public boolean hasNextLong() {
|
||||
return index + Long.BYTES <= end;
|
||||
}
|
||||
|
||||
@Override
|
||||
public long nextLong() {
|
||||
if (!hasNextLong()) {
|
||||
throw new NoSuchElementException("No 'long' value at offet " + currentOffset() + '.');
|
||||
}
|
||||
long val = getLongAtOffset(segment, index, ByteOrder.BIG_ENDIAN);
|
||||
public boolean readLong() {
|
||||
if (index + Long.BYTES <= end) {
|
||||
longValue = getLongAtOffset(segment, index, ByteOrder.BIG_ENDIAN);
|
||||
index += Long.BYTES;
|
||||
return val;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasNextByte() {
|
||||
return index < end;
|
||||
public long getLong() {
|
||||
return longValue;
|
||||
}
|
||||
|
||||
@Override
|
||||
public byte nextByte() {
|
||||
if (!hasNextByte()) {
|
||||
throw new NoSuchElementException("No 'byte' value at offet " + currentOffset() + '.');
|
||||
}
|
||||
byte val = getByteAtOffset(segment, index);
|
||||
public boolean readByte() {
|
||||
if (index < end) {
|
||||
byteValue = getByteAtOffset(segment, index);
|
||||
index++;
|
||||
return val;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public byte getByte() {
|
||||
return byteValue;
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -236,7 +237,7 @@ class MemSegBuf extends RcSupport<Buf, MemSegBuf> implements Buf {
|
||||
}
|
||||
|
||||
@Override
|
||||
public ByteIterator iterateReverse(int fromOffset, int length) {
|
||||
public ByteCursor openReverseCursor(int fromOffset, int length) {
|
||||
if (fromOffset < 0) {
|
||||
throw new IllegalArgumentException("The fromOffset cannot be negative: " + fromOffset + '.');
|
||||
}
|
||||
@ -250,40 +251,42 @@ class MemSegBuf extends RcSupport<Buf, MemSegBuf> implements Buf {
|
||||
throw new IllegalArgumentException("The fromOffset-length would underflow the buffer: " +
|
||||
"fromOffset=" + fromOffset + ", length=" + length + '.');
|
||||
}
|
||||
return new ByteIterator() {
|
||||
return new ByteCursor() {
|
||||
final MemorySegment segment = seg;
|
||||
int index = fromOffset;
|
||||
final int end = index - length;
|
||||
long longValue = -1;
|
||||
byte byteValue = -1;
|
||||
|
||||
@Override
|
||||
public boolean hasNextLong() {
|
||||
return index - Long.BYTES >= end;
|
||||
}
|
||||
|
||||
@Override
|
||||
public long nextLong() {
|
||||
if (!hasNextLong()) {
|
||||
throw new NoSuchElementException("No 'long' value at offet " + currentOffset() + '.');
|
||||
}
|
||||
public boolean readLong() {
|
||||
if (index - Long.BYTES >= end) {
|
||||
index -= 7;
|
||||
long val = getLongAtOffset(segment, index, ByteOrder.LITTLE_ENDIAN);
|
||||
longValue = getLongAtOffset(segment, index, ByteOrder.LITTLE_ENDIAN);
|
||||
index--;
|
||||
return val;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasNextByte() {
|
||||
return index > end;
|
||||
public long getLong() {
|
||||
return longValue;
|
||||
}
|
||||
|
||||
@Override
|
||||
public byte nextByte() {
|
||||
if (!hasNextByte()) {
|
||||
throw new NoSuchElementException("No 'byte' value at offet " + currentOffset() + '.');
|
||||
}
|
||||
byte val = getByteAtOffset(segment, index);
|
||||
public boolean readByte() {
|
||||
if (index > end) {
|
||||
byteValue = getByteAtOffset(segment, index);
|
||||
index--;
|
||||
return val;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public byte getByte() {
|
||||
return byteValue;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -32,7 +32,6 @@ import java.nio.ByteOrder;
|
||||
import java.text.ParseException;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.NoSuchElementException;
|
||||
import java.util.concurrent.ArrayBlockingQueue;
|
||||
import java.util.concurrent.ExecutorService;
|
||||
import java.util.concurrent.Executors;
|
||||
@ -1051,130 +1050,134 @@ public class BufTest {
|
||||
}
|
||||
|
||||
private static void checkByteIteration(Buf buf) {
|
||||
var itr = buf.iterate();
|
||||
assertFalse(itr.hasNextByte());
|
||||
assertFalse(itr.hasNextLong());
|
||||
assertEquals(0, itr.bytesLeft());
|
||||
assertThrows(NoSuchElementException.class, itr::nextLong);
|
||||
assertThrows(NoSuchElementException.class, itr::nextByte);
|
||||
var cursor = buf.openCursor();
|
||||
assertFalse(cursor.readByte());
|
||||
assertFalse(cursor.readLong());
|
||||
assertEquals(0, cursor.bytesLeft());
|
||||
assertEquals((byte) -1, cursor.getByte());
|
||||
assertEquals(-1L, cursor.getLong());
|
||||
|
||||
for (int i = 0; i < 0x27; i++) {
|
||||
buf.writeByte((byte) (i + 1));
|
||||
}
|
||||
int roff = buf.readerOffset();
|
||||
int woff = buf.writerOffset();
|
||||
itr = buf.iterate();
|
||||
assertEquals(0x27, itr.bytesLeft());
|
||||
assertTrue(itr.hasNextByte());
|
||||
assertTrue(itr.hasNextLong());
|
||||
assertEquals(0x0102030405060708L, itr.nextLong());
|
||||
assertEquals(0x1F, itr.bytesLeft());
|
||||
assertTrue(itr.hasNextLong());
|
||||
assertEquals(0x090A0B0C0D0E0F10L, itr.nextLong());
|
||||
assertTrue(itr.hasNextLong());
|
||||
assertEquals(0x17, itr.bytesLeft());
|
||||
assertEquals(0x1112131415161718L, itr.nextLong());
|
||||
assertTrue(itr.hasNextLong());
|
||||
assertEquals(0x0F, itr.bytesLeft());
|
||||
assertEquals(0x191A1B1C1D1E1F20L, itr.nextLong());
|
||||
assertFalse(itr.hasNextLong());
|
||||
assertEquals(7, itr.bytesLeft());
|
||||
assertThrows(NoSuchElementException.class, itr::nextLong);
|
||||
assertTrue(itr.hasNextByte());
|
||||
assertEquals((byte) 0x21, itr.nextByte());
|
||||
assertTrue(itr.hasNextByte());
|
||||
assertEquals(6, itr.bytesLeft());
|
||||
assertEquals((byte) 0x22, itr.nextByte());
|
||||
assertTrue(itr.hasNextByte());
|
||||
assertEquals(5, itr.bytesLeft());
|
||||
assertEquals((byte) 0x23, itr.nextByte());
|
||||
assertTrue(itr.hasNextByte());
|
||||
assertEquals(4, itr.bytesLeft());
|
||||
assertEquals((byte) 0x24, itr.nextByte());
|
||||
assertTrue(itr.hasNextByte());
|
||||
assertEquals(3, itr.bytesLeft());
|
||||
assertEquals((byte) 0x25, itr.nextByte());
|
||||
assertTrue(itr.hasNextByte());
|
||||
assertEquals(2, itr.bytesLeft());
|
||||
assertEquals((byte) 0x26, itr.nextByte());
|
||||
assertTrue(itr.hasNextByte());
|
||||
assertEquals(1, itr.bytesLeft());
|
||||
assertEquals((byte) 0x27, itr.nextByte());
|
||||
assertFalse(itr.hasNextByte());
|
||||
assertEquals(0, itr.bytesLeft());
|
||||
assertThrows(NoSuchElementException.class, itr::nextLong);
|
||||
assertThrows(NoSuchElementException.class, itr::nextByte);
|
||||
cursor = buf.openCursor();
|
||||
assertEquals(0x27, cursor.bytesLeft());
|
||||
assertTrue(cursor.readByte());
|
||||
assertEquals((byte) 0x01, cursor.getByte());
|
||||
assertEquals((byte) 0x01, cursor.getByte());
|
||||
assertTrue(cursor.readLong());
|
||||
assertEquals(0x0203040506070809L, cursor.getLong());
|
||||
assertEquals(0x0203040506070809L, cursor.getLong());
|
||||
assertEquals(0x1E, cursor.bytesLeft());
|
||||
assertTrue(cursor.readLong());
|
||||
assertEquals(0x0A0B0C0D0E0F1011L, cursor.getLong());
|
||||
assertEquals(0x16, cursor.bytesLeft());
|
||||
assertTrue(cursor.readLong());
|
||||
assertEquals(0x1213141516171819L, cursor.getLong());
|
||||
assertEquals(0x0E, cursor.bytesLeft());
|
||||
assertTrue(cursor.readLong());
|
||||
assertEquals(0x1A1B1C1D1E1F2021L, cursor.getLong());
|
||||
assertEquals(6, cursor.bytesLeft());
|
||||
assertFalse(cursor.readLong());
|
||||
assertEquals(6, cursor.bytesLeft());
|
||||
assertEquals(0x1A1B1C1D1E1F2021L, cursor.getLong());
|
||||
assertTrue(cursor.readByte());
|
||||
assertEquals((byte) 0x22, cursor.getByte());
|
||||
assertEquals((byte) 0x22, cursor.getByte());
|
||||
assertEquals(5, cursor.bytesLeft());
|
||||
assertTrue(cursor.readByte());
|
||||
assertEquals((byte) 0x23, cursor.getByte());
|
||||
assertEquals(4, cursor.bytesLeft());
|
||||
assertTrue(cursor.readByte());
|
||||
assertEquals((byte) 0x24, cursor.getByte());
|
||||
assertEquals(3, cursor.bytesLeft());
|
||||
assertTrue(cursor.readByte());
|
||||
assertEquals((byte) 0x25, cursor.getByte());
|
||||
assertEquals(2, cursor.bytesLeft());
|
||||
assertTrue(cursor.readByte());
|
||||
assertEquals((byte) 0x26, cursor.getByte());
|
||||
assertEquals(1, cursor.bytesLeft());
|
||||
assertTrue(cursor.readByte());
|
||||
assertEquals((byte) 0x27, cursor.getByte());
|
||||
assertEquals(0, cursor.bytesLeft());
|
||||
assertFalse(cursor.readByte());
|
||||
assertEquals((byte) 0x27, cursor.getByte());
|
||||
assertEquals((byte) 0x27, cursor.getByte());
|
||||
assertFalse(cursor.readLong());
|
||||
assertEquals(roff, buf.readerOffset());
|
||||
assertEquals(woff, buf.writerOffset());
|
||||
}
|
||||
|
||||
private static void checkByteIterationOfRegion(Buf buf) {
|
||||
assertThrows(IllegalArgumentException.class, () -> buf.iterate(-1, 1));
|
||||
assertThrows(IllegalArgumentException.class, () -> buf.iterate(1, -1));
|
||||
assertThrows(IllegalArgumentException.class, () -> buf.iterate(buf.capacity(), 1));
|
||||
assertThrows(IllegalArgumentException.class, () -> buf.iterate(buf.capacity() - 1, 2));
|
||||
assertThrows(IllegalArgumentException.class, () -> buf.iterate(buf.capacity() - 2, 3));
|
||||
assertThrows(IllegalArgumentException.class, () -> buf.openCursor(-1, 1));
|
||||
assertThrows(IllegalArgumentException.class, () -> buf.openCursor(1, -1));
|
||||
assertThrows(IllegalArgumentException.class, () -> buf.openCursor(buf.capacity(), 1));
|
||||
assertThrows(IllegalArgumentException.class, () -> buf.openCursor(buf.capacity() - 1, 2));
|
||||
assertThrows(IllegalArgumentException.class, () -> buf.openCursor(buf.capacity() - 2, 3));
|
||||
|
||||
var itr = buf.iterate(1, 0);
|
||||
assertFalse(itr.hasNextByte());
|
||||
assertFalse(itr.hasNextLong());
|
||||
assertEquals(0, itr.bytesLeft());
|
||||
assertThrows(NoSuchElementException.class, itr::nextLong);
|
||||
assertThrows(NoSuchElementException.class, itr::nextByte);
|
||||
var cursor = buf.openCursor(1, 0);
|
||||
assertFalse(cursor.readByte());
|
||||
assertFalse(cursor.readLong());
|
||||
assertEquals(0, cursor.bytesLeft());
|
||||
assertEquals((byte) -1, cursor.getByte());
|
||||
assertEquals(-1L, cursor.getLong());
|
||||
|
||||
for (int i = 0; i < 0x27; i++) {
|
||||
buf.writeByte((byte) (i + 1));
|
||||
}
|
||||
int roff = buf.readerOffset();
|
||||
int woff = buf.writerOffset();
|
||||
itr = buf.iterate(buf.readerOffset() + 1, buf.readableBytes() - 2);
|
||||
assertEquals(0x25, itr.bytesLeft());
|
||||
assertTrue(itr.hasNextByte());
|
||||
assertTrue(itr.hasNextLong());
|
||||
assertEquals(0x0203040506070809L, itr.nextLong());
|
||||
assertEquals(0x1D, itr.bytesLeft());
|
||||
assertTrue(itr.hasNextLong());
|
||||
assertEquals(0x0A0B0C0D0E0F1011L, itr.nextLong());
|
||||
assertTrue(itr.hasNextLong());
|
||||
assertEquals(0x15, itr.bytesLeft());
|
||||
assertEquals(0x1213141516171819L, itr.nextLong());
|
||||
assertTrue(itr.hasNextLong());
|
||||
assertEquals(0x0D, itr.bytesLeft());
|
||||
assertEquals(0x1A1B1C1D1E1F2021L, itr.nextLong());
|
||||
assertFalse(itr.hasNextLong());
|
||||
assertEquals(5, itr.bytesLeft());
|
||||
assertThrows(NoSuchElementException.class, itr::nextLong);
|
||||
assertTrue(itr.hasNextByte());
|
||||
assertEquals((byte) 0x22, itr.nextByte());
|
||||
assertTrue(itr.hasNextByte());
|
||||
assertEquals(4, itr.bytesLeft());
|
||||
assertEquals((byte) 0x23, itr.nextByte());
|
||||
assertTrue(itr.hasNextByte());
|
||||
assertEquals(3, itr.bytesLeft());
|
||||
assertEquals((byte) 0x24, itr.nextByte());
|
||||
assertTrue(itr.hasNextByte());
|
||||
assertEquals(2, itr.bytesLeft());
|
||||
assertEquals((byte) 0x25, itr.nextByte());
|
||||
assertTrue(itr.hasNextByte());
|
||||
assertEquals(1, itr.bytesLeft());
|
||||
assertEquals((byte) 0x26, itr.nextByte());
|
||||
assertFalse(itr.hasNextByte());
|
||||
assertEquals(0, itr.bytesLeft());
|
||||
assertThrows(NoSuchElementException.class, itr::nextLong);
|
||||
assertThrows(NoSuchElementException.class, itr::nextByte);
|
||||
cursor = buf.openCursor(buf.readerOffset() + 1, buf.readableBytes() - 2);
|
||||
assertEquals(0x25, cursor.bytesLeft());
|
||||
assertTrue(cursor.readByte());
|
||||
assertEquals((byte) 0x02, cursor.getByte());
|
||||
assertEquals((byte) 0x02, cursor.getByte());
|
||||
assertTrue(cursor.readLong());
|
||||
assertEquals(0x030405060708090AL, cursor.getLong());
|
||||
assertEquals(0x1C, cursor.bytesLeft());
|
||||
assertTrue(cursor.readLong());
|
||||
assertEquals(0x0B0C0D0E0F101112L, cursor.getLong());
|
||||
assertEquals(0x14, cursor.bytesLeft());
|
||||
assertTrue(cursor.readLong());
|
||||
assertEquals(0x131415161718191AL, cursor.getLong());
|
||||
assertEquals(0x0C, cursor.bytesLeft());
|
||||
assertTrue(cursor.readLong());
|
||||
assertEquals(0x1B1C1D1E1F202122L, cursor.getLong());
|
||||
assertEquals(4, cursor.bytesLeft());
|
||||
assertFalse(cursor.readLong());
|
||||
assertEquals(4, cursor.bytesLeft());
|
||||
assertEquals(0x1B1C1D1E1F202122L, cursor.getLong());
|
||||
assertTrue(cursor.readByte());
|
||||
assertEquals((byte) 0x23, cursor.getByte());
|
||||
assertEquals(3, cursor.bytesLeft());
|
||||
assertTrue(cursor.readByte());
|
||||
assertEquals((byte) 0x24, cursor.getByte());
|
||||
assertEquals(2, cursor.bytesLeft());
|
||||
assertTrue(cursor.readByte());
|
||||
assertEquals((byte) 0x25, cursor.getByte());
|
||||
assertEquals(1, cursor.bytesLeft());
|
||||
assertTrue(cursor.readByte());
|
||||
assertEquals((byte) 0x26, cursor.getByte());
|
||||
assertEquals(0, cursor.bytesLeft());
|
||||
assertFalse(cursor.readByte());
|
||||
assertEquals(0, cursor.bytesLeft());
|
||||
assertEquals(0x1B1C1D1E1F202122L, cursor.getLong());
|
||||
assertEquals((byte) 0x26, cursor.getByte());
|
||||
|
||||
itr = buf.iterate(buf.readerOffset() + 1, 2);
|
||||
assertEquals(2, itr.bytesLeft());
|
||||
assertTrue(itr.hasNextByte());
|
||||
assertFalse(itr.hasNextLong());
|
||||
assertEquals((byte) 0x02, itr.nextByte());
|
||||
assertEquals(1, itr.bytesLeft());
|
||||
assertTrue(itr.hasNextByte());
|
||||
assertFalse(itr.hasNextLong());
|
||||
assertEquals((byte) 0x03, itr.nextByte());
|
||||
assertEquals(0, itr.bytesLeft());
|
||||
assertFalse(itr.hasNextByte());
|
||||
assertFalse(itr.hasNextLong());
|
||||
cursor = buf.openCursor(buf.readerOffset() + 1, 2);
|
||||
assertEquals(2, cursor.bytesLeft());
|
||||
assertFalse(cursor.readLong());
|
||||
assertTrue(cursor.readByte());
|
||||
assertEquals((byte) 0x02, cursor.getByte());
|
||||
assertEquals(1, cursor.bytesLeft());
|
||||
assertFalse(cursor.readLong());
|
||||
assertTrue(cursor.readByte());
|
||||
assertEquals((byte) 0x03, cursor.getByte());
|
||||
assertEquals(0, cursor.bytesLeft());
|
||||
assertFalse(cursor.readByte());
|
||||
assertFalse(cursor.readLong());
|
||||
assertEquals(roff, buf.readerOffset());
|
||||
assertEquals(woff, buf.writerOffset());
|
||||
}
|
||||
@ -1204,130 +1207,134 @@ public class BufTest {
|
||||
}
|
||||
|
||||
private static void checkReverseByteIteration(Buf buf) {
|
||||
var itr = buf.iterateReverse();
|
||||
assertFalse(itr.hasNextByte());
|
||||
assertFalse(itr.hasNextLong());
|
||||
assertEquals(0, itr.bytesLeft());
|
||||
assertThrows(NoSuchElementException.class, itr::nextLong);
|
||||
assertThrows(NoSuchElementException.class, itr::nextByte);
|
||||
var cursor = buf.openReverseCursor();
|
||||
assertFalse(cursor.readByte());
|
||||
assertFalse(cursor.readLong());
|
||||
assertEquals(0, cursor.bytesLeft());
|
||||
assertEquals((byte) -1, cursor.getByte());
|
||||
assertEquals(-1L, cursor.getLong());
|
||||
|
||||
for (int i = 0; i < 0x27; i++) {
|
||||
buf.writeByte((byte) (i + 1));
|
||||
}
|
||||
int roff = buf.readerOffset();
|
||||
int woff = buf.writerOffset();
|
||||
itr = buf.iterateReverse();
|
||||
assertEquals(0x27, itr.bytesLeft());
|
||||
assertTrue(itr.hasNextByte());
|
||||
assertTrue(itr.hasNextLong());
|
||||
assertEquals(0x2726252423222120L, itr.nextLong());
|
||||
assertEquals(0x1F, itr.bytesLeft());
|
||||
assertTrue(itr.hasNextLong());
|
||||
assertEquals(0x1F1E1D1C1B1A1918L, itr.nextLong());
|
||||
assertTrue(itr.hasNextLong());
|
||||
assertEquals(0x17, itr.bytesLeft());
|
||||
assertEquals(0x1716151413121110L, itr.nextLong());
|
||||
assertTrue(itr.hasNextLong());
|
||||
assertEquals(0x0F, itr.bytesLeft());
|
||||
assertEquals(0x0F0E0D0C0B0A0908L, itr.nextLong());
|
||||
assertFalse(itr.hasNextLong());
|
||||
assertEquals(7, itr.bytesLeft());
|
||||
assertThrows(NoSuchElementException.class, itr::nextLong);
|
||||
assertTrue(itr.hasNextByte());
|
||||
assertEquals((byte) 0x07, itr.nextByte());
|
||||
assertTrue(itr.hasNextByte());
|
||||
assertEquals(6, itr.bytesLeft());
|
||||
assertEquals((byte) 0x06, itr.nextByte());
|
||||
assertTrue(itr.hasNextByte());
|
||||
assertEquals(5, itr.bytesLeft());
|
||||
assertEquals((byte) 0x05, itr.nextByte());
|
||||
assertTrue(itr.hasNextByte());
|
||||
assertEquals(4, itr.bytesLeft());
|
||||
assertEquals((byte) 0x04, itr.nextByte());
|
||||
assertTrue(itr.hasNextByte());
|
||||
assertEquals(3, itr.bytesLeft());
|
||||
assertEquals((byte) 0x03, itr.nextByte());
|
||||
assertTrue(itr.hasNextByte());
|
||||
assertEquals(2, itr.bytesLeft());
|
||||
assertEquals((byte) 0x02, itr.nextByte());
|
||||
assertTrue(itr.hasNextByte());
|
||||
assertEquals(1, itr.bytesLeft());
|
||||
assertEquals((byte) 0x01, itr.nextByte());
|
||||
assertFalse(itr.hasNextByte());
|
||||
assertEquals(0, itr.bytesLeft());
|
||||
assertThrows(NoSuchElementException.class, itr::nextLong);
|
||||
assertThrows(NoSuchElementException.class, itr::nextByte);
|
||||
cursor = buf.openReverseCursor();
|
||||
assertEquals(0x27, cursor.bytesLeft());
|
||||
assertTrue(cursor.readByte());
|
||||
assertEquals((byte) 0x27, cursor.getByte());
|
||||
assertEquals((byte) 0x27, cursor.getByte());
|
||||
assertTrue(cursor.readLong());
|
||||
assertEquals(0x262524232221201FL, cursor.getLong());
|
||||
assertEquals(0x1E, cursor.bytesLeft());
|
||||
assertTrue(cursor.readLong());
|
||||
assertEquals(0x1E1D1C1B1A191817L, cursor.getLong());
|
||||
assertEquals(0x16, cursor.bytesLeft());
|
||||
assertTrue(cursor.readLong());
|
||||
assertEquals(0x161514131211100FL, cursor.getLong());
|
||||
assertEquals(0x0E, cursor.bytesLeft());
|
||||
assertTrue(cursor.readLong());
|
||||
assertEquals(0x0E0D0C0B0A090807L, cursor.getLong());
|
||||
assertEquals(6, cursor.bytesLeft());
|
||||
assertFalse(cursor.readLong());
|
||||
assertEquals(6, cursor.bytesLeft());
|
||||
assertEquals(0x0E0D0C0B0A090807L, cursor.getLong());
|
||||
assertTrue(cursor.readByte());
|
||||
assertEquals((byte) 0x06, cursor.getByte());
|
||||
assertEquals(5, cursor.bytesLeft());
|
||||
assertTrue(cursor.readByte());
|
||||
assertEquals((byte) 0x05, cursor.getByte());
|
||||
assertEquals(4, cursor.bytesLeft());
|
||||
assertTrue(cursor.readByte());
|
||||
assertEquals((byte) 0x04, cursor.getByte());
|
||||
assertEquals(3, cursor.bytesLeft());
|
||||
assertTrue(cursor.readByte());
|
||||
assertEquals((byte) 0x03, cursor.getByte());
|
||||
assertEquals(2, cursor.bytesLeft());
|
||||
assertTrue(cursor.readByte());
|
||||
assertEquals((byte) 0x02, cursor.getByte());
|
||||
assertEquals(1, cursor.bytesLeft());
|
||||
assertTrue(cursor.readByte());
|
||||
assertEquals((byte) 0x01, cursor.getByte());
|
||||
assertEquals(0, cursor.bytesLeft());
|
||||
assertFalse(cursor.readByte());
|
||||
assertEquals((byte) 0x01, cursor.getByte());
|
||||
assertFalse(cursor.readByte());
|
||||
assertEquals(0, cursor.bytesLeft());
|
||||
assertEquals(0x0E0D0C0B0A090807L, cursor.getLong());
|
||||
assertEquals(roff, buf.readerOffset());
|
||||
assertEquals(woff, buf.writerOffset());
|
||||
}
|
||||
|
||||
private static void checkReverseByteIterationOfRegion(Buf buf) {
|
||||
assertThrows(IllegalArgumentException.class, () -> buf.iterateReverse(-1, 0));
|
||||
assertThrows(IllegalArgumentException.class, () -> buf.iterateReverse(0, -1));
|
||||
assertThrows(IllegalArgumentException.class, () -> buf.iterateReverse(0, 2));
|
||||
assertThrows(IllegalArgumentException.class, () -> buf.iterateReverse(1, 3));
|
||||
assertThrows(IllegalArgumentException.class, () -> buf.iterateReverse(buf.capacity(), 0));
|
||||
assertThrows(IllegalArgumentException.class, () -> buf.openReverseCursor(-1, 0));
|
||||
assertThrows(IllegalArgumentException.class, () -> buf.openReverseCursor(0, -1));
|
||||
assertThrows(IllegalArgumentException.class, () -> buf.openReverseCursor(0, 2));
|
||||
assertThrows(IllegalArgumentException.class, () -> buf.openReverseCursor(1, 3));
|
||||
assertThrows(IllegalArgumentException.class, () -> buf.openReverseCursor(buf.capacity(), 0));
|
||||
|
||||
var itr = buf.iterateReverse(1, 0);
|
||||
assertFalse(itr.hasNextByte());
|
||||
assertFalse(itr.hasNextLong());
|
||||
assertEquals(0, itr.bytesLeft());
|
||||
assertThrows(NoSuchElementException.class, itr::nextLong);
|
||||
assertThrows(NoSuchElementException.class, itr::nextByte);
|
||||
var cursor = buf.openReverseCursor(1, 0);
|
||||
assertFalse(cursor.readByte());
|
||||
assertFalse(cursor.readLong());
|
||||
assertEquals(0, cursor.bytesLeft());
|
||||
assertEquals((byte) -1, cursor.getByte());
|
||||
assertEquals(-1L, cursor.getLong());
|
||||
|
||||
for (int i = 0; i < 0x27; i++) {
|
||||
buf.writeByte((byte) (i + 1));
|
||||
}
|
||||
int roff = buf.readerOffset();
|
||||
int woff = buf.writerOffset();
|
||||
itr = buf.iterateReverse(buf.writerOffset() - 2, buf.readableBytes() - 2);
|
||||
assertEquals(0x25, itr.bytesLeft());
|
||||
assertTrue(itr.hasNextByte());
|
||||
assertTrue(itr.hasNextLong());
|
||||
assertEquals(0x262524232221201FL, itr.nextLong());
|
||||
assertEquals(0x1D, itr.bytesLeft());
|
||||
assertTrue(itr.hasNextLong());
|
||||
assertEquals(0x1E1D1C1B1A191817L, itr.nextLong());
|
||||
assertTrue(itr.hasNextLong());
|
||||
assertEquals(0x15, itr.bytesLeft());
|
||||
assertEquals(0x161514131211100FL, itr.nextLong());
|
||||
assertTrue(itr.hasNextLong());
|
||||
assertEquals(0x0D, itr.bytesLeft());
|
||||
assertEquals(0x0E0D0C0B0A090807L, itr.nextLong());
|
||||
assertFalse(itr.hasNextLong());
|
||||
assertEquals(5, itr.bytesLeft());
|
||||
assertThrows(NoSuchElementException.class, itr::nextLong);
|
||||
assertTrue(itr.hasNextByte());
|
||||
assertEquals((byte) 0x06, itr.nextByte());
|
||||
assertTrue(itr.hasNextByte());
|
||||
assertEquals(4, itr.bytesLeft());
|
||||
assertEquals((byte) 0x05, itr.nextByte());
|
||||
assertTrue(itr.hasNextByte());
|
||||
assertEquals(3, itr.bytesLeft());
|
||||
assertEquals((byte) 0x04, itr.nextByte());
|
||||
assertTrue(itr.hasNextByte());
|
||||
assertEquals(2, itr.bytesLeft());
|
||||
assertEquals((byte) 0x03, itr.nextByte());
|
||||
assertTrue(itr.hasNextByte());
|
||||
assertEquals(1, itr.bytesLeft());
|
||||
assertEquals((byte) 0x02, itr.nextByte());
|
||||
assertFalse(itr.hasNextByte());
|
||||
assertEquals(0, itr.bytesLeft());
|
||||
assertThrows(NoSuchElementException.class, itr::nextLong);
|
||||
assertThrows(NoSuchElementException.class, itr::nextByte);
|
||||
cursor = buf.openReverseCursor(buf.writerOffset() - 2, buf.readableBytes() - 2);
|
||||
assertEquals(0x25, cursor.bytesLeft());
|
||||
assertTrue(cursor.readByte());
|
||||
assertEquals((byte) 0x26, cursor.getByte());
|
||||
assertEquals((byte) 0x26, cursor.getByte());
|
||||
assertTrue(cursor.readLong());
|
||||
assertEquals(0x2524232221201F1EL, cursor.getLong());
|
||||
assertEquals(0x1C, cursor.bytesLeft());
|
||||
assertTrue(cursor.readLong());
|
||||
assertEquals(0x1D1C1B1A19181716L, cursor.getLong());
|
||||
assertEquals(0x14, cursor.bytesLeft());
|
||||
assertTrue(cursor.readLong());
|
||||
assertEquals(0x1514131211100F0EL, cursor.getLong());
|
||||
assertEquals(0x0C, cursor.bytesLeft());
|
||||
assertTrue(cursor.readLong());
|
||||
assertEquals(0x0D0C0B0A09080706L, cursor.getLong());
|
||||
assertEquals(4, cursor.bytesLeft());
|
||||
assertFalse(cursor.readLong());
|
||||
assertEquals(4, cursor.bytesLeft());
|
||||
assertEquals(0x0D0C0B0A09080706L, cursor.getLong());
|
||||
assertTrue(cursor.readByte());
|
||||
assertEquals((byte) 0x05, cursor.getByte());
|
||||
assertEquals(3, cursor.bytesLeft());
|
||||
assertTrue(cursor.readByte());
|
||||
assertEquals((byte) 0x04, cursor.getByte());
|
||||
assertEquals(2, cursor.bytesLeft());
|
||||
assertTrue(cursor.readByte());
|
||||
assertEquals((byte) 0x03, cursor.getByte());
|
||||
assertEquals(1, cursor.bytesLeft());
|
||||
assertTrue(cursor.readByte());
|
||||
assertEquals((byte) 0x02, cursor.getByte());
|
||||
assertEquals(0, cursor.bytesLeft());
|
||||
assertFalse(cursor.readByte());
|
||||
assertEquals((byte) 0x02, cursor.getByte());
|
||||
assertFalse(cursor.readByte());
|
||||
assertEquals(0, cursor.bytesLeft());
|
||||
assertEquals(0x0D0C0B0A09080706L, cursor.getLong());
|
||||
|
||||
itr = buf.iterateReverse(buf.readerOffset() + 2, 2);
|
||||
assertEquals(2, itr.bytesLeft());
|
||||
assertTrue(itr.hasNextByte());
|
||||
assertFalse(itr.hasNextLong());
|
||||
assertEquals((byte) 0x03, itr.nextByte());
|
||||
assertEquals(1, itr.bytesLeft());
|
||||
assertTrue(itr.hasNextByte());
|
||||
assertFalse(itr.hasNextLong());
|
||||
assertEquals((byte) 0x02, itr.nextByte());
|
||||
assertEquals(0, itr.bytesLeft());
|
||||
assertFalse(itr.hasNextByte());
|
||||
assertFalse(itr.hasNextLong());
|
||||
cursor = buf.openReverseCursor(buf.readerOffset() + 2, 2);
|
||||
assertEquals(2, cursor.bytesLeft());
|
||||
assertFalse(cursor.readLong());
|
||||
assertTrue(cursor.readByte());
|
||||
assertEquals((byte) 0x03, cursor.getByte());
|
||||
assertEquals(1, cursor.bytesLeft());
|
||||
assertFalse(cursor.readLong());
|
||||
assertTrue(cursor.readByte());
|
||||
assertEquals((byte) 0x02, cursor.getByte());
|
||||
assertEquals(0, cursor.bytesLeft());
|
||||
assertFalse(cursor.readByte());
|
||||
assertFalse(cursor.readLong());
|
||||
assertEquals(roff, buf.readerOffset());
|
||||
assertEquals(woff, buf.writerOffset());
|
||||
}
|
||||
|
@ -92,26 +92,26 @@ public class ByteIterationBenchmark {
|
||||
|
||||
@Benchmark
|
||||
public long sum() {
|
||||
var itr = buf.iterate();
|
||||
var itr = buf.openCursor();
|
||||
long sum = 0;
|
||||
while (itr.hasNextLong()) {
|
||||
sum += itr.nextLong();
|
||||
while (itr.readLong()) {
|
||||
sum += itr.getLong();
|
||||
}
|
||||
while (itr.hasNextByte()) {
|
||||
sum += itr.nextByte();
|
||||
while (itr.readByte()) {
|
||||
sum += itr.getByte();
|
||||
}
|
||||
return sum;
|
||||
}
|
||||
|
||||
@Benchmark
|
||||
public long sumReverse() {
|
||||
var itr = buf.iterateReverse();
|
||||
var itr = buf.openReverseCursor();
|
||||
long sum = 0;
|
||||
while (itr.hasNextLong()) {
|
||||
sum += itr.nextLong();
|
||||
while (itr.readLong()) {
|
||||
sum += itr.getLong();
|
||||
}
|
||||
while (itr.hasNextByte()) {
|
||||
sum += itr.nextByte();
|
||||
while (itr.readByte()) {
|
||||
sum += itr.getByte();
|
||||
}
|
||||
return sum;
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user