Split ByteBuf.forEachByte() into forEachByte() and forEachByteDesc()
- Related: #1378 - As suggested by @liqweed
This commit is contained in:
parent
9804741fb3
commit
ac39cad5ff
@ -767,7 +767,7 @@ public abstract class AbstractByteBuf implements ByteBuf {
|
||||
@Override
|
||||
public ByteBuf writeByte(int value) {
|
||||
ensureWritable(1);
|
||||
setByte(writerIndex ++, value);
|
||||
setByte(writerIndex++, value);
|
||||
return this;
|
||||
}
|
||||
|
||||
@ -1042,22 +1042,12 @@ public abstract class AbstractByteBuf implements ByteBuf {
|
||||
|
||||
@Override
|
||||
public int forEachByte(int fromIndex, int toIndex, ByteBufProcessor processor) {
|
||||
if (fromIndex < toIndex) {
|
||||
return forEachByteAsc(fromIndex, toIndex, processor);
|
||||
} else if (fromIndex > toIndex) {
|
||||
return forEachByteDesc(fromIndex, toIndex, processor);
|
||||
} else {
|
||||
checkIndex(fromIndex);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
private int forEachByteAsc(int fromIndex, int toIndex, ByteBufProcessor processor) {
|
||||
if (fromIndex < 0 || toIndex > capacity()) {
|
||||
if (fromIndex < 0 || fromIndex > toIndex || toIndex > capacity()) {
|
||||
throw new IndexOutOfBoundsException(String.format(
|
||||
"fromIndex: %d, toIndex: %d (expected: 0 <= fromIndex < toIndex <= capacity(%d))",
|
||||
"fromIndex: %d, toIndex: %d (expected: 0 <= fromIndex <= toIndex <= capacity(%d))",
|
||||
fromIndex, toIndex, capacity()));
|
||||
}
|
||||
|
||||
return forEachByteAsc0(fromIndex, toIndex, processor);
|
||||
}
|
||||
|
||||
@ -1066,6 +1056,10 @@ public abstract class AbstractByteBuf implements ByteBuf {
|
||||
throw new NullPointerException("processor");
|
||||
}
|
||||
|
||||
if (fromIndex == toIndex) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
int i = fromIndex;
|
||||
try {
|
||||
do {
|
||||
@ -1081,22 +1075,32 @@ public abstract class AbstractByteBuf implements ByteBuf {
|
||||
return -1;
|
||||
}
|
||||
|
||||
private int forEachByteDesc(int fromIndex, int toIndex, ByteBufProcessor processor) {
|
||||
if (toIndex < -1 || fromIndex >= capacity()) {
|
||||
@Override
|
||||
public int forEachByteDesc(ByteBufProcessor processor) {
|
||||
return forEachByteDesc0(readerIndex, writerIndex, processor);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int forEachByteDesc(int toIndex, int fromIndex, ByteBufProcessor processor) {
|
||||
if (toIndex < 0 || toIndex > fromIndex || fromIndex > capacity()) {
|
||||
throw new IndexOutOfBoundsException(String.format(
|
||||
"fromIndex: %d, toIndex: %d (expected: -1 <= toIndex < fromIndex < capacity(%d))",
|
||||
fromIndex, toIndex, capacity()));
|
||||
"toIndex: %d, fromIndex: %d (expected: 0 <= toIndex <= fromIndex <= capacity(%d))",
|
||||
toIndex, fromIndex, capacity()));
|
||||
}
|
||||
|
||||
return forEachByteDesc0(toIndex, fromIndex, processor);
|
||||
}
|
||||
|
||||
private int forEachByteDesc0(int toIndex, int fromIndex, ByteBufProcessor processor) {
|
||||
if (processor == null) {
|
||||
throw new NullPointerException("processor");
|
||||
}
|
||||
|
||||
int i = fromIndex;
|
||||
int i = fromIndex - 1;
|
||||
try {
|
||||
do {
|
||||
i -= processor.process(this, i, _getByte(i));
|
||||
} while (i > toIndex);
|
||||
} while (i >= toIndex);
|
||||
} catch (Signal signal) {
|
||||
signal.expect(ByteBufProcessor.ABORT);
|
||||
return i;
|
||||
|
@ -1700,7 +1700,7 @@ public interface ByteBuf extends ReferenceCounted, Comparable<ByteBuf> {
|
||||
int bytesBefore(int index, int length, ByteBufIndexFinder indexFinder);
|
||||
|
||||
/**
|
||||
* Iterates over the readable bytes of this buffer with the specified {@code processor}.
|
||||
* Iterates over the readable bytes of this buffer with the specified {@code processor} in ascending order.
|
||||
*
|
||||
* @return {@code -1} if the processor iterated to or beyond the end of the readable bytes.
|
||||
* If the {@code processor} raised {@link ByteBufProcessor#ABORT}, the last-visited index will be returned.
|
||||
@ -1708,22 +1708,31 @@ public interface ByteBuf extends ReferenceCounted, Comparable<ByteBuf> {
|
||||
int forEachByte(ByteBufProcessor processor);
|
||||
|
||||
/**
|
||||
* Iterates over the specified area of this buffer with the specified {@code processor}.
|
||||
* <ul>
|
||||
* <li>If {@code fromIndex} is less than {@code toIndex}, the iteration is performed in an ascending order.
|
||||
* Iterates over the specified area of this buffer with the specified {@code processor} in ascending order.
|
||||
* ({@code [fromIndex, fromIndex)} i.e. {@code fromIndex}, {@code (fromIndex + 1)}, .. {@code (toIndex - 1)})
|
||||
* </li>
|
||||
* <li>If {@code fromIndex} is greater than {@code toIndex}, the iteration is performed in a descending order.
|
||||
* ({@code [toIndex, fromIndex)} i.e. {@code (fromIndex)}, {@code (fromIndex - 1)}, ... {@code toIndex + 1})
|
||||
* </li>
|
||||
* <li>If {@code fromIndex} is equal to {@code toIndex}, {@code -1} is returned immediately.</li>
|
||||
* </ul>
|
||||
*
|
||||
* @return {@code -1} if the processor iterated to or beyond the end of the specified area.
|
||||
* If the {@code processor} raised {@link ByteBufProcessor#ABORT}, the last-visited index will be returned.
|
||||
*/
|
||||
int forEachByte(int fromIndex, int toIndex, ByteBufProcessor processor);
|
||||
|
||||
/**
|
||||
* Iterates over the readable bytes of this buffer with the specified {@code processor} in descending order.
|
||||
*
|
||||
* @return {@code -1} if the processor iterated to or beyond the beginning of the readable bytes.
|
||||
* If the {@code processor} raised {@link ByteBufProcessor#ABORT}, the last-visited index will be returned.
|
||||
*/
|
||||
int forEachByteDesc(ByteBufProcessor processor);
|
||||
|
||||
/**
|
||||
* Iterates over the specified area of this buffer with the specified {@code processor} in descending order.
|
||||
* ({@code [toIndex, fromIndex)} i.e. {@code (fromIndex - 1)}, {@code (fromIndex - 2)}, ... {@code toIndex})
|
||||
*
|
||||
* @return {@code -1} if the processor iterated to or beyond the beginning of the specified area.
|
||||
* If the {@code processor} raised {@link ByteBufProcessor#ABORT}, the last-visited index will be returned.
|
||||
*/
|
||||
int forEachByteDesc(int toIndex, int fromIndex, ByteBufProcessor processor);
|
||||
|
||||
/**
|
||||
* Returns a copy of this buffer's readable bytes. Modifying the content
|
||||
* of the returned buffer or this buffer does not affect each other at all.
|
||||
|
@ -294,7 +294,12 @@ public class DuplicatedByteBuf extends AbstractDerivedByteBuf {
|
||||
|
||||
@Override
|
||||
public int forEachByte(int fromIndex, int toIndex, ByteBufProcessor processor) {
|
||||
return buffer.forEachByte(fromIndex, toIndex, processor);
|
||||
return buffer.forEachByte(fromIndex, toIndex, new WrappedByteBufProcessor(this, processor));
|
||||
}
|
||||
|
||||
@Override
|
||||
public int forEachByteDesc(int toIndex, int fromIndex, ByteBufProcessor processor) {
|
||||
return buffer.forEachByteDesc(toIndex, fromIndex, new WrappedByteBufProcessor(this, processor));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -719,7 +719,20 @@ public final class EmptyByteBuf implements ByteBuf {
|
||||
|
||||
@Override
|
||||
public int forEachByte(int fromIndex, int toIndex, ByteBufProcessor processor) {
|
||||
if (fromIndex != 0 && fromIndex != toIndex) {
|
||||
if (fromIndex != 0 || fromIndex != toIndex) {
|
||||
throw new IndexOutOfBoundsException();
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int forEachByteDesc(ByteBufProcessor processor) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int forEachByteDesc(int toIndex, int fromIndex, ByteBufProcessor processor) {
|
||||
if (toIndex != 0 || toIndex != fromIndex) {
|
||||
throw new IndexOutOfBoundsException();
|
||||
}
|
||||
return -1;
|
||||
|
@ -297,7 +297,12 @@ public class ReadOnlyByteBuf extends AbstractDerivedByteBuf {
|
||||
|
||||
@Override
|
||||
public int forEachByte(int fromIndex, int toIndex, ByteBufProcessor processor) {
|
||||
return buffer.forEachByte(fromIndex, toIndex, processor);
|
||||
return buffer.forEachByte(fromIndex, toIndex, new WrappedByteBufProcessor(this, processor));
|
||||
}
|
||||
|
||||
@Override
|
||||
public int forEachByteDesc(int toIndex, int fromIndex, ByteBufProcessor processor) {
|
||||
return buffer.forEachByteDesc(toIndex, fromIndex, new WrappedByteBufProcessor(this, processor));
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -276,7 +276,19 @@ public class SlicedByteBuf extends AbstractDerivedByteBuf {
|
||||
|
||||
@Override
|
||||
public int forEachByte(int fromIndex, int toIndex, ByteBufProcessor processor) {
|
||||
int ret = buffer.forEachByte(fromIndex + adjustment, toIndex + adjustment, new SlicedByteBufProcessor(processor));
|
||||
int ret = buffer.forEachByte(
|
||||
fromIndex + adjustment, toIndex + adjustment, new SlicedByteBufProcessor(processor));
|
||||
if (ret >= adjustment) {
|
||||
return ret - adjustment;
|
||||
} else {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public int forEachByteDesc(int toIndex, int fromIndex, ByteBufProcessor processor) {
|
||||
int ret = buffer.forEachByteDesc(
|
||||
toIndex + adjustment, fromIndex + adjustment, new SlicedByteBufProcessor(processor));
|
||||
if (ret >= adjustment) {
|
||||
return ret - adjustment;
|
||||
} else {
|
||||
|
@ -721,12 +721,22 @@ public final class SwappedByteBuf implements ByteBuf {
|
||||
|
||||
@Override
|
||||
public int forEachByte(ByteBufProcessor processor) {
|
||||
return buf.forEachByte(new SwappedByteBufProcessor(processor));
|
||||
return buf.forEachByte(new WrappedByteBufProcessor(this, processor));
|
||||
}
|
||||
|
||||
@Override
|
||||
public int forEachByte(int fromIndex, int toIndex, ByteBufProcessor processor) {
|
||||
return buf.forEachByte(fromIndex, toIndex, new SwappedByteBufProcessor(processor));
|
||||
return buf.forEachByte(fromIndex, toIndex, new WrappedByteBufProcessor(this, processor));
|
||||
}
|
||||
|
||||
@Override
|
||||
public int forEachByteDesc(ByteBufProcessor processor) {
|
||||
return buf.forEachByteDesc(new WrappedByteBufProcessor(this, processor));
|
||||
}
|
||||
|
||||
@Override
|
||||
public int forEachByteDesc(int toIndex, int fromIndex, ByteBufProcessor processor) {
|
||||
return buf.forEachByteDesc(toIndex, fromIndex, new WrappedByteBufProcessor(this, processor));
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -897,21 +907,4 @@ public final class SwappedByteBuf implements ByteBuf {
|
||||
return indexFinder.find(SwappedByteBuf.this, guessedIndex);
|
||||
}
|
||||
}
|
||||
|
||||
private final class SwappedByteBufProcessor implements ByteBufProcessor {
|
||||
|
||||
private final ByteBufProcessor processor;
|
||||
|
||||
SwappedByteBufProcessor(ByteBufProcessor processor) {
|
||||
if (processor == null) {
|
||||
throw new NullPointerException("processor");
|
||||
}
|
||||
this.processor = processor;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int process(ByteBuf buf, int index, byte value) throws Exception {
|
||||
return processor.process(SwappedByteBuf.this, index, value);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -727,12 +727,22 @@ final class UnreleasableByteBuf implements ByteBuf {
|
||||
|
||||
@Override
|
||||
public int forEachByte(ByteBufProcessor processor) {
|
||||
return buf.forEachByte(processor);
|
||||
return buf.forEachByte(new WrappedByteBufProcessor(this, processor));
|
||||
}
|
||||
|
||||
@Override
|
||||
public int forEachByte(int fromIndex, int toIndex, ByteBufProcessor processor) {
|
||||
return buf.forEachByte(fromIndex, toIndex, processor);
|
||||
return buf.forEachByte(fromIndex, toIndex, new WrappedByteBufProcessor(this, processor));
|
||||
}
|
||||
|
||||
@Override
|
||||
public int forEachByteDesc(ByteBufProcessor processor) {
|
||||
return buf.forEachByteDesc(new WrappedByteBufProcessor(this, processor));
|
||||
}
|
||||
|
||||
@Override
|
||||
public int forEachByteDesc(int toIndex, int fromIndex, ByteBufProcessor processor) {
|
||||
return buf.forEachByteDesc(toIndex, fromIndex, new WrappedByteBufProcessor(this, processor));
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -0,0 +1,35 @@
|
||||
/*
|
||||
* Copyright 2013 The Netty Project
|
||||
*
|
||||
* The Netty Project licenses this file to you under the Apache License,
|
||||
* version 2.0 (the "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at:
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
* License for the specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
|
||||
package io.netty.buffer;
|
||||
|
||||
final class WrappedByteBufProcessor implements ByteBufProcessor {
|
||||
private final ByteBuf buffer;
|
||||
private final ByteBufProcessor processor;
|
||||
|
||||
WrappedByteBufProcessor(ByteBuf buffer, ByteBufProcessor processor) {
|
||||
if (processor == null) {
|
||||
throw new NullPointerException("processor");
|
||||
}
|
||||
this.buffer = buffer;
|
||||
this.processor = processor;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int process(ByteBuf buf, int index, byte value) throws Exception {
|
||||
return processor.process(buffer, index, value);
|
||||
}
|
||||
}
|
@ -1663,8 +1663,8 @@ public abstract class AbstractByteBufTest {
|
||||
|
||||
@Override
|
||||
public int process(ByteBuf buf, int index, byte value) throws Exception {
|
||||
assertThat(value, is((byte) (i + 1)));
|
||||
assertThat(index, is(i));
|
||||
assertThat(value, is((byte) (i + 1)));
|
||||
i ++;
|
||||
lastIndex.set(index);
|
||||
return 1;
|
||||
@ -1687,9 +1687,9 @@ public abstract class AbstractByteBufTest {
|
||||
|
||||
@Override
|
||||
public int process(ByteBuf buf, int index, byte value) throws Exception {
|
||||
assertThat(value, is((byte) (i + 1)));
|
||||
assertThat(index, is(i));
|
||||
i ++;
|
||||
assertThat(value, is((byte) (i + 1)));
|
||||
i++;
|
||||
|
||||
if (index == stop) {
|
||||
throw ABORT;
|
||||
@ -1707,20 +1707,19 @@ public abstract class AbstractByteBufTest {
|
||||
}
|
||||
|
||||
final AtomicInteger lastIndex = new AtomicInteger();
|
||||
buffer.setIndex(CAPACITY / 4, CAPACITY * 3 / 4);
|
||||
assertThat(buffer.forEachByte(CAPACITY * 3 / 4, CAPACITY / 4, new ByteBufProcessor() {
|
||||
int i = CAPACITY * 3 / 4;
|
||||
assertThat(buffer.forEachByteDesc(CAPACITY / 4, CAPACITY * 3 / 4, new ByteBufProcessor() {
|
||||
int i = CAPACITY * 3 / 4 - 1;
|
||||
|
||||
@Override
|
||||
public int process(ByteBuf buf, int index, byte value) throws Exception {
|
||||
assertThat(value, is((byte) (i + 1)));
|
||||
assertThat(index, is(i));
|
||||
i --;
|
||||
assertThat(value, is((byte) (i + 1)));
|
||||
i--;
|
||||
lastIndex.set(index);
|
||||
return 1;
|
||||
}
|
||||
}), is(-1));
|
||||
|
||||
assertThat(lastIndex.get(), is(CAPACITY / 4 + 1));
|
||||
assertThat(lastIndex.get(), is(CAPACITY / 4));
|
||||
}
|
||||
}
|
||||
|
@ -43,16 +43,16 @@ public class ByteBufProcessorTest {
|
||||
public void testBackward() {
|
||||
ByteBuf buf = Unpooled.copiedBuffer("abc\r\n\ndef\r\rghi\n\njkl\0\0mno \t\tx", CharsetUtil.ISO_8859_1);
|
||||
|
||||
assertEquals(27, buf.forEachByte(buf.capacity() - 1, -1, ByteBufProcessor.FIND_LINEAR_WHITESPACE));
|
||||
assertEquals(23, buf.forEachByte(27, -1, ByteBufProcessor.FIND_NON_LINEAR_WHITESPACE));
|
||||
assertEquals(20, buf.forEachByte(23, -1, ByteBufProcessor.FIND_NUL));
|
||||
assertEquals(18, buf.forEachByte(20, -1, ByteBufProcessor.FIND_NON_NUL));
|
||||
assertEquals(15, buf.forEachByte(18, -1, ByteBufProcessor.FIND_LF));
|
||||
assertEquals(13, buf.forEachByte(15, -1, ByteBufProcessor.FIND_NON_LF));
|
||||
assertEquals(10, buf.forEachByte(13, -1, ByteBufProcessor.FIND_CR));
|
||||
assertEquals(8, buf.forEachByte(10, -1, ByteBufProcessor.FIND_NON_CR));
|
||||
assertEquals(5, buf.forEachByte(8, -1, ByteBufProcessor.FIND_CRLF));
|
||||
assertEquals(2, buf.forEachByte(5, -1, ByteBufProcessor.FIND_NON_CRLF));
|
||||
assertEquals(-1, buf.forEachByte(2, -1, ByteBufProcessor.FIND_CRLF));
|
||||
assertEquals(27, buf.forEachByteDesc(0, buf.writerIndex(), ByteBufProcessor.FIND_LINEAR_WHITESPACE));
|
||||
assertEquals(23, buf.forEachByteDesc(0, 28, ByteBufProcessor.FIND_NON_LINEAR_WHITESPACE));
|
||||
assertEquals(20, buf.forEachByteDesc(0, 24, ByteBufProcessor.FIND_NUL));
|
||||
assertEquals(18, buf.forEachByteDesc(0, 21, ByteBufProcessor.FIND_NON_NUL));
|
||||
assertEquals(15, buf.forEachByteDesc(0, 19, ByteBufProcessor.FIND_LF));
|
||||
assertEquals(13, buf.forEachByteDesc(0, 16, ByteBufProcessor.FIND_NON_LF));
|
||||
assertEquals(10, buf.forEachByteDesc(0, 14, ByteBufProcessor.FIND_CR));
|
||||
assertEquals(8, buf.forEachByteDesc(0, 11, ByteBufProcessor.FIND_NON_CR));
|
||||
assertEquals(5, buf.forEachByteDesc(0, 9, ByteBufProcessor.FIND_CRLF));
|
||||
assertEquals(2, buf.forEachByteDesc(0, 6, ByteBufProcessor.FIND_NON_CRLF));
|
||||
assertEquals(-1, buf.forEachByteDesc(0, 3, ByteBufProcessor.FIND_CRLF));
|
||||
}
|
||||
}
|
||||
|
@ -378,7 +378,7 @@ final class ReplayingDecoderBuffer implements ByteBuf {
|
||||
@Override
|
||||
public int forEachByte(ByteBufProcessor processor) {
|
||||
int ret = buffer.forEachByte(processor);
|
||||
if (ret < 0) {
|
||||
if (!terminated && ret < 0) {
|
||||
throw REPLAY;
|
||||
} else {
|
||||
return ret;
|
||||
@ -387,21 +387,6 @@ final class ReplayingDecoderBuffer implements ByteBuf {
|
||||
|
||||
@Override
|
||||
public int forEachByte(int fromIndex, int toIndex, ByteBufProcessor processor) {
|
||||
if (fromIndex < toIndex) {
|
||||
return forEachByteAsc(fromIndex, toIndex, processor);
|
||||
} else if (fromIndex > toIndex) {
|
||||
return forEachByteDesc(fromIndex, toIndex, processor);
|
||||
} else {
|
||||
checkIndex(fromIndex, 0);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
private int forEachByteAsc(int fromIndex, int toIndex, ByteBufProcessor processor) {
|
||||
if (fromIndex < 0) {
|
||||
throw new IndexOutOfBoundsException("fromIndex: " + fromIndex);
|
||||
}
|
||||
|
||||
final int writerIndex = buffer.writerIndex();
|
||||
if (fromIndex >= writerIndex) {
|
||||
throw REPLAY;
|
||||
@ -419,16 +404,22 @@ final class ReplayingDecoderBuffer implements ByteBuf {
|
||||
}
|
||||
}
|
||||
|
||||
private int forEachByteDesc(int fromIndex, int toIndex, ByteBufProcessor processor) {
|
||||
if (toIndex < -1) {
|
||||
throw new IndexOutOfBoundsException("toIndex: " + toIndex);
|
||||
@Override
|
||||
public int forEachByteDesc(ByteBufProcessor processor) {
|
||||
if (terminated) {
|
||||
return buffer.forEachByteDesc(processor);
|
||||
} else {
|
||||
throw new UnreplayableOperationException();
|
||||
}
|
||||
}
|
||||
|
||||
if (fromIndex >= buffer.writerIndex()) {
|
||||
@Override
|
||||
public int forEachByteDesc(int toIndex, int fromIndex, ByteBufProcessor processor) {
|
||||
if (fromIndex > buffer.writerIndex()) {
|
||||
throw REPLAY;
|
||||
}
|
||||
|
||||
return buffer.forEachByte(fromIndex, toIndex, processor);
|
||||
return buffer.forEachByteDesc(toIndex, fromIndex, processor);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
Loading…
Reference in New Issue
Block a user