diff --git a/buffer/src/main/java/io/netty/buffer/AbstractByteBuf.java b/buffer/src/main/java/io/netty/buffer/AbstractByteBuf.java
index 3f97be30c8..7dbc536bb9 100644
--- a/buffer/src/main/java/io/netty/buffer/AbstractByteBuf.java
+++ b/buffer/src/main/java/io/netty/buffer/AbstractByteBuf.java
@@ -15,6 +15,7 @@
*/
package io.netty.buffer;
+import io.netty.util.ByteProcessor;
import io.netty.util.IllegalReferenceCountException;
import io.netty.util.ResourceLeakDetector;
import io.netty.util.internal.PlatformDependent;
@@ -965,7 +966,7 @@ public abstract class AbstractByteBuf extends ByteBuf {
}
@Override
- public int forEachByte(ByteBufProcessor processor) {
+ public int forEachByte(ByteProcessor processor) {
int index = readerIndex;
int length = writerIndex - index;
ensureAccessible();
@@ -973,12 +974,12 @@ public abstract class AbstractByteBuf extends ByteBuf {
}
@Override
- public int forEachByte(int index, int length, ByteBufProcessor processor) {
+ public int forEachByte(int index, int length, ByteProcessor processor) {
checkIndex(index, length);
return forEachByteAsc0(index, length, processor);
}
- private int forEachByteAsc0(int index, int length, ByteBufProcessor processor) {
+ private int forEachByteAsc0(int index, int length, ByteProcessor processor) {
if (processor == null) {
throw new NullPointerException("processor");
}
@@ -1005,7 +1006,7 @@ public abstract class AbstractByteBuf extends ByteBuf {
}
@Override
- public int forEachByteDesc(ByteBufProcessor processor) {
+ public int forEachByteDesc(ByteProcessor processor) {
int index = readerIndex;
int length = writerIndex - index;
ensureAccessible();
@@ -1013,13 +1014,13 @@ public abstract class AbstractByteBuf extends ByteBuf {
}
@Override
- public int forEachByteDesc(int index, int length, ByteBufProcessor processor) {
+ public int forEachByteDesc(int index, int length, ByteProcessor processor) {
checkIndex(index, length);
return forEachByteDesc0(index, length, processor);
}
- private int forEachByteDesc0(int index, int length, ByteBufProcessor processor) {
+ private int forEachByteDesc0(int index, int length, ByteProcessor processor) {
if (processor == null) {
throw new NullPointerException("processor");
diff --git a/buffer/src/main/java/io/netty/buffer/AdvancedLeakAwareByteBuf.java b/buffer/src/main/java/io/netty/buffer/AdvancedLeakAwareByteBuf.java
index 3866baf967..ef683596ca 100644
--- a/buffer/src/main/java/io/netty/buffer/AdvancedLeakAwareByteBuf.java
+++ b/buffer/src/main/java/io/netty/buffer/AdvancedLeakAwareByteBuf.java
@@ -16,6 +16,7 @@
package io.netty.buffer;
+import io.netty.util.ByteProcessor;
import io.netty.util.ResourceLeak;
import java.io.IOException;
@@ -599,25 +600,25 @@ final class AdvancedLeakAwareByteBuf extends WrappedByteBuf {
}
@Override
- public int forEachByte(ByteBufProcessor processor) {
+ public int forEachByte(ByteProcessor processor) {
leak.record();
return super.forEachByte(processor);
}
@Override
- public int forEachByte(int index, int length, ByteBufProcessor processor) {
+ public int forEachByte(int index, int length, ByteProcessor processor) {
leak.record();
return super.forEachByte(index, length, processor);
}
@Override
- public int forEachByteDesc(ByteBufProcessor processor) {
+ public int forEachByteDesc(ByteProcessor processor) {
leak.record();
return super.forEachByteDesc(processor);
}
@Override
- public int forEachByteDesc(int index, int length, ByteBufProcessor processor) {
+ public int forEachByteDesc(int index, int length, ByteProcessor processor) {
leak.record();
return super.forEachByteDesc(index, length, processor);
}
diff --git a/buffer/src/main/java/io/netty/buffer/ByteBuf.java b/buffer/src/main/java/io/netty/buffer/ByteBuf.java
index 4d399c683e..13d03ca262 100644
--- a/buffer/src/main/java/io/netty/buffer/ByteBuf.java
+++ b/buffer/src/main/java/io/netty/buffer/ByteBuf.java
@@ -15,6 +15,7 @@
*/
package io.netty.buffer;
+import io.netty.util.ByteProcessor;
import io.netty.util.ReferenceCounted;
import java.io.IOException;
@@ -178,7 +179,7 @@ import java.nio.charset.UnsupportedCharsetException;
*
* For simple single-byte searches, use {@link #indexOf(int, int, byte)} and {@link #bytesBefore(int, int, byte)}.
* {@link #bytesBefore(byte)} is especially useful when you deal with a {@code NUL}-terminated string.
- * For complicated searches, use {@link #forEachByte(int, int, ByteBufProcessor)} with a {@link ByteBufProcessor}
+ * For complicated searches, use {@link #forEachByte(int, int, ByteProcessor)} with a {@link ByteProcessor}
* implementation.
*
*
Mark and reset
@@ -1605,26 +1606,26 @@ public abstract class ByteBuf implements ReferenceCounted, Comparable {
* 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.
- * The last-visited index If the {@link ByteBufProcessor#process(byte)} returned {@code false}.
+ * The last-visited index If the {@link ByteProcessor#process(byte)} returned {@code false}.
*/
- public abstract int forEachByte(ByteBufProcessor processor);
+ public abstract int forEachByte(ByteProcessor processor);
/**
* Iterates over the specified area of this buffer with the specified {@code processor} in ascending order.
* (i.e. {@code index}, {@code (index + 1)}, .. {@code (index + length - 1)})
*
* @return {@code -1} if the processor iterated to or beyond the end of the specified area.
- * The last-visited index If the {@link ByteBufProcessor#process(byte)} returned {@code false}.
+ * The last-visited index If the {@link ByteProcessor#process(byte)} returned {@code false}.
*/
- public abstract int forEachByte(int index, int length, ByteBufProcessor processor);
+ public abstract int forEachByte(int index, int length, ByteProcessor 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.
- * The last-visited index If the {@link ByteBufProcessor#process(byte)} returned {@code false}.
+ * The last-visited index If the {@link ByteProcessor#process(byte)} returned {@code false}.
*/
- public abstract int forEachByteDesc(ByteBufProcessor processor);
+ public abstract int forEachByteDesc(ByteProcessor processor);
/**
* Iterates over the specified area of this buffer with the specified {@code processor} in descending order.
@@ -1632,9 +1633,9 @@ public abstract class ByteBuf implements ReferenceCounted, Comparable {
*
*
* @return {@code -1} if the processor iterated to or beyond the beginning of the specified area.
- * The last-visited index If the {@link ByteBufProcessor#process(byte)} returned {@code false}.
+ * The last-visited index If the {@link ByteProcessor#process(byte)} returned {@code false}.
*/
- public abstract int forEachByteDesc(int index, int length, ByteBufProcessor processor);
+ public abstract int forEachByteDesc(int index, int length, ByteProcessor processor);
/**
* Returns a copy of this buffer's readable bytes. Modifying the content
diff --git a/buffer/src/main/java/io/netty/buffer/ByteBufProcessor.java b/buffer/src/main/java/io/netty/buffer/ByteBufProcessor.java
index a1323a0ce6..13d063ff9e 100644
--- a/buffer/src/main/java/io/netty/buffer/ByteBufProcessor.java
+++ b/buffer/src/main/java/io/netty/buffer/ByteBufProcessor.java
@@ -16,10 +16,15 @@
package io.netty.buffer;
-public interface ByteBufProcessor {
+import io.netty.util.ByteProcessor;
+
+/**
+ * @deprecated Use {@link ByteProcessor}.
+ */
+public interface ByteBufProcessor extends ByteProcessor {
/**
- * Aborts on a {@code NUL (0x00)}.
+ * @deprecated Use {@link ByteProcessor#FIND_NULL}.
*/
ByteBufProcessor FIND_NUL = new ByteBufProcessor() {
@Override
@@ -29,7 +34,7 @@ public interface ByteBufProcessor {
};
/**
- * Aborts on a non-{@code NUL (0x00)}.
+ * @deprecated Use {@link ByteProcessor#FIND_NON_NUL}.
*/
ByteBufProcessor FIND_NON_NUL = new ByteBufProcessor() {
@Override
@@ -39,7 +44,7 @@ public interface ByteBufProcessor {
};
/**
- * Aborts on a {@code CR ('\r')}.
+ * @deprecated Use {@link ByteProcessor#FIND_CR}.
*/
ByteBufProcessor FIND_CR = new ByteBufProcessor() {
@Override
@@ -49,7 +54,7 @@ public interface ByteBufProcessor {
};
/**
- * Aborts on a non-{@code CR ('\r')}.
+ * @deprecated Use {@link ByteProcessor#FIND_NON_CR}.
*/
ByteBufProcessor FIND_NON_CR = new ByteBufProcessor() {
@Override
@@ -59,7 +64,7 @@ public interface ByteBufProcessor {
};
/**
- * Aborts on a {@code LF ('\n')}.
+ * @deprecated Use {@link ByteProcessor#FIND_LF}.
*/
ByteBufProcessor FIND_LF = new ByteBufProcessor() {
@Override
@@ -69,7 +74,7 @@ public interface ByteBufProcessor {
};
/**
- * Aborts on a non-{@code LF ('\n')}.
+ * @deprecated Use {@link ByteProcessor#FIND_NON_LF}.
*/
ByteBufProcessor FIND_NON_LF = new ByteBufProcessor() {
@Override
@@ -79,7 +84,7 @@ public interface ByteBufProcessor {
};
/**
- * Aborts on a {@code CR ('\r')} or a {@code LF ('\n')}.
+ * @deprecated Use {@link ByteProcessor#FIND_CRLF}.
*/
ByteBufProcessor FIND_CRLF = new ByteBufProcessor() {
@Override
@@ -89,7 +94,7 @@ public interface ByteBufProcessor {
};
/**
- * Aborts on a byte which is neither a {@code CR ('\r')} nor a {@code LF ('\n')}.
+ * @deprecated Use {@link ByteProcessor#FIND_NON_CRLF}.
*/
ByteBufProcessor FIND_NON_CRLF = new ByteBufProcessor() {
@Override
@@ -99,7 +104,7 @@ public interface ByteBufProcessor {
};
/**
- * Aborts on a linear whitespace (a ({@code ' '} or a {@code '\t'}).
+ * @deprecated Use {@link ByteProcessor#FIND_LINEAR_WHITESPACE}.
*/
ByteBufProcessor FIND_LINEAR_WHITESPACE = new ByteBufProcessor() {
@Override
@@ -109,7 +114,7 @@ public interface ByteBufProcessor {
};
/**
- * Aborts on a byte which is not a linear whitespace (neither {@code ' '} nor {@code '\t'}).
+ * @deprecated Use {@link ByteProcessor#FIND_NON_LINEAR_WHITESPACE}.
*/
ByteBufProcessor FIND_NON_LINEAR_WHITESPACE = new ByteBufProcessor() {
@Override
@@ -117,10 +122,4 @@ public interface ByteBufProcessor {
return value == ' ' || value == '\t';
}
};
-
- /**
- * @return {@code true} if the processor wants to continue the loop and handle the next byte in the buffer.
- * {@code false} if the processor wants to stop handling bytes and abort the loop.
- */
- boolean process(byte value) throws Exception;
}
diff --git a/buffer/src/main/java/io/netty/buffer/ByteBufUtil.java b/buffer/src/main/java/io/netty/buffer/ByteBufUtil.java
index 871db9bcdd..fbbe2b1c0f 100644
--- a/buffer/src/main/java/io/netty/buffer/ByteBufUtil.java
+++ b/buffer/src/main/java/io/netty/buffer/ByteBufUtil.java
@@ -15,6 +15,8 @@
*/
package io.netty.buffer;
+import static io.netty.util.internal.ObjectUtil.checkNotNull;
+import io.netty.util.ByteString;
import io.netty.util.CharsetUtil;
import io.netty.util.Recycler;
import io.netty.util.Recycler.Handle;
@@ -31,6 +33,7 @@ import java.nio.charset.Charset;
import java.nio.charset.CharsetDecoder;
import java.nio.charset.CharsetEncoder;
import java.nio.charset.CoderResult;
+import java.util.Arrays;
import java.util.Locale;
/**
@@ -549,6 +552,85 @@ public final class ByteBufUtil {
}
}
+ /**
+ * Create a copy of the underlying storage from {@link value} into a byte array.
+ * The copy will start at {@link ByteBuf#readerIndex()} and copy {@link ByteBuf#readableBytes()} bytes.
+ */
+ public static byte[] getBytes(ByteBuf buf) {
+ return getBytes(buf, checkNotNull(buf, "buf").readerIndex(), buf.readableBytes());
+ }
+
+ /**
+ * Create a copy of the underlying storage from {@link buf} into a byte array.
+ * The copy will start at {@code start} and copy {@code length} bytes.
+ */
+ public static byte[] getBytes(ByteBuf buf, int start, int length) {
+ return getBytes(buf, start, length, true);
+ }
+
+ /**
+ * Return an array of the underlying storage from {@link buf} into a byte array.
+ * The copy will start at {@code start} and copy {@code length} bytes.
+ * If {@code copy} is true a copy will be made of the memory.
+ * If {@code copy} is false the underlying storage will be shared, if possible.
+ */
+ public static byte[] getBytes(ByteBuf buf, int start, int length, boolean copy) {
+ if (start < 0 || length > checkNotNull(buf, "buf").capacity() - start) {
+ throw new IndexOutOfBoundsException("expected: " + "0 <= start(" + start + ") <= start + length(" + length
+ + ") <= " + "buf.capacity(" + buf.capacity() + ')');
+ }
+
+ if (buf.hasArray()) {
+ if (copy || start != 0 || length != buf.capacity()) {
+ int baseOffset = buf.arrayOffset() + start;
+ return Arrays.copyOfRange(buf.array(), baseOffset, baseOffset + length);
+ } else {
+ return buf.array();
+ }
+ }
+
+ byte[] v = new byte[length];
+ buf.getBytes(start, v);
+ return v;
+ }
+
+ /**
+ * Copies the content of {@code src} to a {@link ByteBuf} using {@link ByteBuf#writeBytes(byte[], int, int)}.
+ * @param src The source of the data to copy.
+ * @param srcIdx the starting offset of characters to copy.
+ * @param dst the destination byte array.
+ * @param dstIdx the starting offset in the destination byte array.
+ * @param length the number of characters to copy.
+ */
+ public static void copy(ByteString src, int srcIdx, ByteBuf dst, int dstIdx, int length) {
+ final int thisLen = src.length();
+
+ if (srcIdx < 0 || length > thisLen - srcIdx) {
+ throw new IndexOutOfBoundsException("expected: " + "0 <= srcIdx(" + srcIdx + ") <= srcIdx + length("
+ + length + ") <= srcLen(" + thisLen + ')');
+ }
+
+ checkNotNull(dst, "dst").setBytes(dstIdx, src.array(), srcIdx, length);
+ }
+
+ /**
+ * Copies the content of {@code src} to a {@link ByteBuf} using {@link ByteBuf#writeBytes(byte[], int, int)}.
+ * @param src The source of the data to copy.
+ * @param srcIdx the starting offset of characters to copy.
+ * @param dst the destination byte array.
+ * @param length the number of characters to copy.
+ */
+ public static void copy(ByteString src, int srcIdx, ByteBuf dst, int length) {
+ final int thisLen = src.length();
+
+ if (srcIdx < 0 || length > thisLen - srcIdx) {
+ throw new IndexOutOfBoundsException("expected: " + "0 <= srcIdx(" + srcIdx + ") <= srcIdx + length("
+ + length + ") <= srcLen(" + thisLen + ')');
+ }
+
+ checkNotNull(dst, "dst").writeBytes(src.array(), srcIdx, length);
+ }
+
static final class ThreadLocalUnsafeDirectByteBuf extends UnpooledUnsafeDirectByteBuf {
private static final Recycler RECYCLER =
diff --git a/buffer/src/main/java/io/netty/buffer/DuplicatedByteBuf.java b/buffer/src/main/java/io/netty/buffer/DuplicatedByteBuf.java
index 43ff8b895c..d6f89644cd 100644
--- a/buffer/src/main/java/io/netty/buffer/DuplicatedByteBuf.java
+++ b/buffer/src/main/java/io/netty/buffer/DuplicatedByteBuf.java
@@ -15,6 +15,8 @@
*/
package io.netty.buffer;
+import io.netty.util.ByteProcessor;
+
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
@@ -293,12 +295,12 @@ public class DuplicatedByteBuf extends AbstractDerivedByteBuf {
}
@Override
- public int forEachByte(int index, int length, ByteBufProcessor processor) {
+ public int forEachByte(int index, int length, ByteProcessor processor) {
return buffer.forEachByte(index, length, processor);
}
@Override
- public int forEachByteDesc(int index, int length, ByteBufProcessor processor) {
+ public int forEachByteDesc(int index, int length, ByteProcessor processor) {
return buffer.forEachByteDesc(index, length, processor);
}
}
diff --git a/buffer/src/main/java/io/netty/buffer/EmptyByteBuf.java b/buffer/src/main/java/io/netty/buffer/EmptyByteBuf.java
index 9f8db89741..80facdb7fa 100644
--- a/buffer/src/main/java/io/netty/buffer/EmptyByteBuf.java
+++ b/buffer/src/main/java/io/netty/buffer/EmptyByteBuf.java
@@ -16,6 +16,7 @@
package io.netty.buffer;
+import io.netty.util.ByteProcessor;
import io.netty.util.internal.EmptyArrays;
import io.netty.util.internal.PlatformDependent;
import io.netty.util.internal.StringUtil;
@@ -668,23 +669,23 @@ public final class EmptyByteBuf extends ByteBuf {
}
@Override
- public int forEachByte(ByteBufProcessor processor) {
+ public int forEachByte(ByteProcessor processor) {
return -1;
}
@Override
- public int forEachByte(int index, int length, ByteBufProcessor processor) {
+ public int forEachByte(int index, int length, ByteProcessor processor) {
checkIndex(index, length);
return -1;
}
@Override
- public int forEachByteDesc(ByteBufProcessor processor) {
+ public int forEachByteDesc(ByteProcessor processor) {
return -1;
}
@Override
- public int forEachByteDesc(int index, int length, ByteBufProcessor processor) {
+ public int forEachByteDesc(int index, int length, ByteProcessor processor) {
checkIndex(index, length);
return -1;
}
diff --git a/buffer/src/main/java/io/netty/buffer/ReadOnlyByteBuf.java b/buffer/src/main/java/io/netty/buffer/ReadOnlyByteBuf.java
index a284c527d4..b6e46ab64c 100644
--- a/buffer/src/main/java/io/netty/buffer/ReadOnlyByteBuf.java
+++ b/buffer/src/main/java/io/netty/buffer/ReadOnlyByteBuf.java
@@ -15,6 +15,8 @@
*/
package io.netty.buffer;
+import io.netty.util.ByteProcessor;
+
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
@@ -296,12 +298,12 @@ public class ReadOnlyByteBuf extends AbstractDerivedByteBuf {
}
@Override
- public int forEachByte(int index, int length, ByteBufProcessor processor) {
+ public int forEachByte(int index, int length, ByteProcessor processor) {
return buffer.forEachByte(index, length, processor);
}
@Override
- public int forEachByteDesc(int index, int length, ByteBufProcessor processor) {
+ public int forEachByteDesc(int index, int length, ByteProcessor processor) {
return buffer.forEachByteDesc(index, length, processor);
}
diff --git a/buffer/src/main/java/io/netty/buffer/SlicedByteBuf.java b/buffer/src/main/java/io/netty/buffer/SlicedByteBuf.java
index 4c109fe62e..7683e13bc2 100644
--- a/buffer/src/main/java/io/netty/buffer/SlicedByteBuf.java
+++ b/buffer/src/main/java/io/netty/buffer/SlicedByteBuf.java
@@ -15,6 +15,8 @@
*/
package io.netty.buffer;
+import io.netty.util.ByteProcessor;
+
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
@@ -275,7 +277,7 @@ public class SlicedByteBuf extends AbstractDerivedByteBuf {
}
@Override
- public int forEachByte(int index, int length, ByteBufProcessor processor) {
+ public int forEachByte(int index, int length, ByteProcessor processor) {
int ret = buffer.forEachByte(index + adjustment, length, processor);
if (ret >= adjustment) {
return ret - adjustment;
@@ -285,7 +287,7 @@ public class SlicedByteBuf extends AbstractDerivedByteBuf {
}
@Override
- public int forEachByteDesc(int index, int length, ByteBufProcessor processor) {
+ public int forEachByteDesc(int index, int length, ByteProcessor processor) {
int ret = buffer.forEachByteDesc(index + adjustment, length, processor);
if (ret >= adjustment) {
return ret - adjustment;
diff --git a/buffer/src/main/java/io/netty/buffer/SwappedByteBuf.java b/buffer/src/main/java/io/netty/buffer/SwappedByteBuf.java
index 3c917c4f84..df257b45c9 100644
--- a/buffer/src/main/java/io/netty/buffer/SwappedByteBuf.java
+++ b/buffer/src/main/java/io/netty/buffer/SwappedByteBuf.java
@@ -15,6 +15,8 @@
*/
package io.netty.buffer;
+import io.netty.util.ByteProcessor;
+
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
@@ -680,22 +682,22 @@ public class SwappedByteBuf extends ByteBuf {
}
@Override
- public int forEachByte(ByteBufProcessor processor) {
+ public int forEachByte(ByteProcessor processor) {
return buf.forEachByte(processor);
}
@Override
- public int forEachByte(int index, int length, ByteBufProcessor processor) {
+ public int forEachByte(int index, int length, ByteProcessor processor) {
return buf.forEachByte(index, length, processor);
}
@Override
- public int forEachByteDesc(ByteBufProcessor processor) {
+ public int forEachByteDesc(ByteProcessor processor) {
return buf.forEachByteDesc(processor);
}
@Override
- public int forEachByteDesc(int index, int length, ByteBufProcessor processor) {
+ public int forEachByteDesc(int index, int length, ByteProcessor processor) {
return buf.forEachByteDesc(index, length, processor);
}
diff --git a/buffer/src/main/java/io/netty/buffer/WrappedByteBuf.java b/buffer/src/main/java/io/netty/buffer/WrappedByteBuf.java
index eae17e0e74..d3050851cb 100644
--- a/buffer/src/main/java/io/netty/buffer/WrappedByteBuf.java
+++ b/buffer/src/main/java/io/netty/buffer/WrappedByteBuf.java
@@ -16,6 +16,7 @@
package io.netty.buffer;
+import io.netty.util.ByteProcessor;
import io.netty.util.internal.StringUtil;
import java.io.IOException;
@@ -668,22 +669,22 @@ public class WrappedByteBuf extends ByteBuf {
}
@Override
- public int forEachByte(ByteBufProcessor processor) {
+ public int forEachByte(ByteProcessor processor) {
return buf.forEachByte(processor);
}
@Override
- public int forEachByte(int index, int length, ByteBufProcessor processor) {
+ public int forEachByte(int index, int length, ByteProcessor processor) {
return buf.forEachByte(index, length, processor);
}
@Override
- public int forEachByteDesc(ByteBufProcessor processor) {
+ public int forEachByteDesc(ByteProcessor processor) {
return buf.forEachByteDesc(processor);
}
@Override
- public int forEachByteDesc(int index, int length, ByteBufProcessor processor) {
+ public int forEachByteDesc(int index, int length, ByteProcessor processor) {
return buf.forEachByteDesc(index, length, processor);
}
diff --git a/buffer/src/test/java/io/netty/buffer/AbstractByteBufTest.java b/buffer/src/test/java/io/netty/buffer/AbstractByteBufTest.java
index 684bbb2042..7bccf0b876 100644
--- a/buffer/src/test/java/io/netty/buffer/AbstractByteBufTest.java
+++ b/buffer/src/test/java/io/netty/buffer/AbstractByteBufTest.java
@@ -15,9 +15,11 @@
*/
package io.netty.buffer;
+import io.netty.util.ByteProcessor;
import io.netty.util.CharsetUtil;
import io.netty.util.IllegalReferenceCountException;
import io.netty.util.internal.ThreadLocalRandom;
+
import org.junit.After;
import org.junit.Assume;
import org.junit.Before;
@@ -1666,7 +1668,7 @@ public abstract class AbstractByteBufTest {
final AtomicInteger lastIndex = new AtomicInteger();
buffer.setIndex(CAPACITY / 4, CAPACITY * 3 / 4);
- assertThat(buffer.forEachByte(new ByteBufProcessor() {
+ assertThat(buffer.forEachByte(new ByteProcessor() {
int i = CAPACITY / 4;
@Override
@@ -1689,7 +1691,7 @@ public abstract class AbstractByteBufTest {
}
final int stop = CAPACITY / 2;
- assertThat(buffer.forEachByte(CAPACITY / 3, CAPACITY / 3, new ByteBufProcessor() {
+ assertThat(buffer.forEachByte(CAPACITY / 3, CAPACITY / 3, new ByteProcessor() {
int i = CAPACITY / 3;
@Override
@@ -1713,7 +1715,7 @@ public abstract class AbstractByteBufTest {
}
final AtomicInteger lastIndex = new AtomicInteger();
- assertThat(buffer.forEachByteDesc(CAPACITY / 4, CAPACITY * 2 / 4, new ByteBufProcessor() {
+ assertThat(buffer.forEachByteDesc(CAPACITY / 4, CAPACITY * 2 / 4, new ByteProcessor() {
int i = CAPACITY * 3 / 4 - 1;
@Override
@@ -2377,22 +2379,22 @@ public abstract class AbstractByteBufTest {
@Test(expected = IllegalReferenceCountException.class)
public void testForEachByteAfterRelease() {
- releasedBuffer().forEachByte(new TestByteBufProcessor());
+ releasedBuffer().forEachByte(new TestByteProcessor());
}
@Test(expected = IllegalReferenceCountException.class)
public void testForEachByteAfterRelease1() {
- releasedBuffer().forEachByte(0, 1, new TestByteBufProcessor());
+ releasedBuffer().forEachByte(0, 1, new TestByteProcessor());
}
@Test(expected = IllegalReferenceCountException.class)
public void testForEachByteDescAfterRelease() {
- releasedBuffer().forEachByteDesc(new TestByteBufProcessor());
+ releasedBuffer().forEachByteDesc(new TestByteProcessor());
}
@Test(expected = IllegalReferenceCountException.class)
public void testForEachByteDescAfterRelease1() {
- releasedBuffer().forEachByteDesc(0, 1, new TestByteBufProcessor());
+ releasedBuffer().forEachByteDesc(0, 1, new TestByteProcessor());
}
@Test(expected = IllegalReferenceCountException.class)
@@ -2647,7 +2649,7 @@ public abstract class AbstractByteBufTest {
}
}
- private static final class TestByteBufProcessor implements ByteBufProcessor {
+ private static final class TestByteProcessor implements ByteProcessor {
@Override
public boolean process(byte value) throws Exception {
return true;
diff --git a/buffer/src/test/java/io/netty/buffer/ByteBufProcessorTest.java b/buffer/src/test/java/io/netty/buffer/ByteBufProcessorTest.java
deleted file mode 100644
index 26e833489e..0000000000
--- a/buffer/src/test/java/io/netty/buffer/ByteBufProcessorTest.java
+++ /dev/null
@@ -1,63 +0,0 @@
-/*
- * 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;
-
-import io.netty.util.CharsetUtil;
-import org.junit.Test;
-
-import static io.netty.util.ReferenceCountUtil.releaseLater;
-import static org.junit.Assert.*;
-
-public class ByteBufProcessorTest {
- @Test
- public void testForward() {
- final ByteBuf buf = releaseLater(
- Unpooled.copiedBuffer("abc\r\n\ndef\r\rghi\n\njkl\0\0mno \t\tx", CharsetUtil.ISO_8859_1));
- final int length = buf.readableBytes();
-
- assertEquals(3, buf.forEachByte(0, length, ByteBufProcessor.FIND_CRLF));
- assertEquals(6, buf.forEachByte(3, length - 3, ByteBufProcessor.FIND_NON_CRLF));
- assertEquals(9, buf.forEachByte(6, length - 6, ByteBufProcessor.FIND_CR));
- assertEquals(11, buf.forEachByte(9, length - 9, ByteBufProcessor.FIND_NON_CR));
- assertEquals(14, buf.forEachByte(11, length - 11, ByteBufProcessor.FIND_LF));
- assertEquals(16, buf.forEachByte(14, length - 14, ByteBufProcessor.FIND_NON_LF));
- assertEquals(19, buf.forEachByte(16, length - 16, ByteBufProcessor.FIND_NUL));
- assertEquals(21, buf.forEachByte(19, length - 19, ByteBufProcessor.FIND_NON_NUL));
- assertEquals(24, buf.forEachByte(21, length - 21, ByteBufProcessor.FIND_LINEAR_WHITESPACE));
- assertEquals(28, buf.forEachByte(24, length - 24, ByteBufProcessor.FIND_NON_LINEAR_WHITESPACE));
- assertEquals(-1, buf.forEachByte(28, length - 28, ByteBufProcessor.FIND_LINEAR_WHITESPACE));
- }
-
- @Test
- public void testBackward() {
- final ByteBuf buf = releaseLater(
- Unpooled.copiedBuffer("abc\r\n\ndef\r\rghi\n\njkl\0\0mno \t\tx", CharsetUtil.ISO_8859_1));
- final int length = buf.readableBytes();
-
- assertEquals(27, buf.forEachByteDesc(0, length, 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));
- }
-}
diff --git a/buffer/src/test/java/io/netty/buffer/ByteProcessorTest.java b/buffer/src/test/java/io/netty/buffer/ByteProcessorTest.java
new file mode 100644
index 0000000000..6f2f3044ed
--- /dev/null
+++ b/buffer/src/test/java/io/netty/buffer/ByteProcessorTest.java
@@ -0,0 +1,64 @@
+/*
+ * 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;
+
+import static io.netty.util.ReferenceCountUtil.releaseLater;
+import static org.junit.Assert.assertEquals;
+import io.netty.util.ByteProcessor;
+import io.netty.util.CharsetUtil;
+
+import org.junit.Test;
+
+public class ByteProcessorTest {
+ @Test
+ public void testForward() {
+ final ByteBuf buf = releaseLater(
+ Unpooled.copiedBuffer("abc\r\n\ndef\r\rghi\n\njkl\0\0mno \t\tx", CharsetUtil.ISO_8859_1));
+ final int length = buf.readableBytes();
+
+ assertEquals(3, buf.forEachByte(0, length, ByteProcessor.FIND_CRLF));
+ assertEquals(6, buf.forEachByte(3, length - 3, ByteProcessor.FIND_NON_CRLF));
+ assertEquals(9, buf.forEachByte(6, length - 6, ByteProcessor.FIND_CR));
+ assertEquals(11, buf.forEachByte(9, length - 9, ByteProcessor.FIND_NON_CR));
+ assertEquals(14, buf.forEachByte(11, length - 11, ByteProcessor.FIND_LF));
+ assertEquals(16, buf.forEachByte(14, length - 14, ByteProcessor.FIND_NON_LF));
+ assertEquals(19, buf.forEachByte(16, length - 16, ByteProcessor.FIND_NUL));
+ assertEquals(21, buf.forEachByte(19, length - 19, ByteProcessor.FIND_NON_NUL));
+ assertEquals(24, buf.forEachByte(21, length - 21, ByteProcessor.FIND_LINEAR_WHITESPACE));
+ assertEquals(28, buf.forEachByte(24, length - 24, ByteProcessor.FIND_NON_LINEAR_WHITESPACE));
+ assertEquals(-1, buf.forEachByte(28, length - 28, ByteProcessor.FIND_LINEAR_WHITESPACE));
+ }
+
+ @Test
+ public void testBackward() {
+ final ByteBuf buf = releaseLater(
+ Unpooled.copiedBuffer("abc\r\n\ndef\r\rghi\n\njkl\0\0mno \t\tx", CharsetUtil.ISO_8859_1));
+ final int length = buf.readableBytes();
+
+ assertEquals(27, buf.forEachByteDesc(0, length, ByteProcessor.FIND_LINEAR_WHITESPACE));
+ assertEquals(23, buf.forEachByteDesc(0, 28, ByteProcessor.FIND_NON_LINEAR_WHITESPACE));
+ assertEquals(20, buf.forEachByteDesc(0, 24, ByteProcessor.FIND_NUL));
+ assertEquals(18, buf.forEachByteDesc(0, 21, ByteProcessor.FIND_NON_NUL));
+ assertEquals(15, buf.forEachByteDesc(0, 19, ByteProcessor.FIND_LF));
+ assertEquals(13, buf.forEachByteDesc(0, 16, ByteProcessor.FIND_NON_LF));
+ assertEquals(10, buf.forEachByteDesc(0, 14, ByteProcessor.FIND_CR));
+ assertEquals(8, buf.forEachByteDesc(0, 11, ByteProcessor.FIND_NON_CR));
+ assertEquals(5, buf.forEachByteDesc(0, 9, ByteProcessor.FIND_CRLF));
+ assertEquals(2, buf.forEachByteDesc(0, 6, ByteProcessor.FIND_NON_CRLF));
+ assertEquals(-1, buf.forEachByteDesc(0, 3, ByteProcessor.FIND_CRLF));
+ }
+}
diff --git a/codec-haproxy/src/main/java/io/netty/handler/codec/haproxy/HAProxyMessage.java b/codec-haproxy/src/main/java/io/netty/handler/codec/haproxy/HAProxyMessage.java
index f9e9d3370b..7172c00d03 100644
--- a/codec-haproxy/src/main/java/io/netty/handler/codec/haproxy/HAProxyMessage.java
+++ b/codec-haproxy/src/main/java/io/netty/handler/codec/haproxy/HAProxyMessage.java
@@ -16,8 +16,8 @@
package io.netty.handler.codec.haproxy;
import io.netty.buffer.ByteBuf;
-import io.netty.buffer.ByteBufProcessor;
import io.netty.handler.codec.haproxy.HAProxyProxiedProtocol.AddressFamily;
+import io.netty.util.ByteProcessor;
import io.netty.util.CharsetUtil;
import io.netty.util.NetUtil;
import io.netty.util.internal.StringUtil;
@@ -166,7 +166,7 @@ public final class HAProxyMessage {
Math.min(addressInfoLen, header.readableBytes()) + " bytes (expected: 216+ bytes)");
}
int startIdx = header.readerIndex();
- int addressEnd = header.forEachByte(startIdx, 108, ByteBufProcessor.FIND_NUL);
+ int addressEnd = header.forEachByte(startIdx, 108, ByteProcessor.FIND_NUL);
if (addressEnd == -1) {
addressLen = 108;
} else {
@@ -176,7 +176,7 @@ public final class HAProxyMessage {
startIdx += 108;
- addressEnd = header.forEachByte(startIdx, 108, ByteBufProcessor.FIND_NUL);
+ addressEnd = header.forEachByte(startIdx, 108, ByteProcessor.FIND_NUL);
if (addressEnd == -1) {
addressLen = 108;
} else {
diff --git a/codec-http/src/main/java/io/netty/handler/codec/http/DefaultHttpHeaders.java b/codec-http/src/main/java/io/netty/handler/codec/http/DefaultHttpHeaders.java
index d39df58477..3c8f8248a0 100644
--- a/codec-http/src/main/java/io/netty/handler/codec/http/DefaultHttpHeaders.java
+++ b/codec-http/src/main/java/io/netty/handler/codec/http/DefaultHttpHeaders.java
@@ -16,12 +16,14 @@
package io.netty.handler.codec.http;
import io.netty.buffer.ByteBuf;
-import io.netty.handler.codec.AsciiString;
import io.netty.handler.codec.DefaultHeaders.NameConverter;
import io.netty.handler.codec.DefaultTextHeaders;
import io.netty.handler.codec.DefaultTextHeaders.DefaultTextValueTypeConverter;
import io.netty.handler.codec.Headers.EntryVisitor;
import io.netty.handler.codec.TextHeaders;
+import io.netty.util.AsciiString;
+import io.netty.util.ByteProcessor;
+import io.netty.util.internal.PlatformDependent;
import java.util.Calendar;
import java.util.Date;
@@ -94,17 +96,34 @@ public class DefaultHttpHeaders extends HttpHeaders {
return seq;
}
- private static void validateValue(AsciiString seq) {
- int state = 0;
- // Start looping through each of the character
- final int start = seq.arrayOffset();
- final int end = start + seq.length();
- final byte[] array = seq.array();
- for (int index = start; index < end; index++) {
- state = validateValueChar(seq, state, (char) (array[index] & 0xFF));
+ private static final class ValidateValueProcessor implements ByteProcessor {
+ private final CharSequence seq;
+ private int state;
+
+ public ValidateValueProcessor(CharSequence seq) {
+ this.seq = seq;
}
- if (state != 0) {
+ @Override
+ public boolean process(byte value) throws Exception {
+ state = validateValueChar(state, (char) value, seq);
+ return true;
+ }
+
+ public int state() {
+ return state;
+ }
+ }
+
+ private static void validateValue(AsciiString seq) {
+ ValidateValueProcessor processor = new ValidateValueProcessor(seq);
+ try {
+ seq.forEachByte(processor);
+ } catch (Throwable t) {
+ PlatformDependent.throwException(t);
+ }
+
+ if (processor.state() != 0) {
throw new IllegalArgumentException("a header value must not end with '\\r' or '\\n':" + seq);
}
}
@@ -113,7 +132,7 @@ public class DefaultHttpHeaders extends HttpHeaders {
int state = 0;
// Start looping through each of the character
for (int index = 0; index < seq.length(); index++) {
- state = validateValueChar(seq, state, seq.charAt(index));
+ state = validateValueChar(state, seq.charAt(index), seq);
}
if (state != 0) {
@@ -121,16 +140,16 @@ public class DefaultHttpHeaders extends HttpHeaders {
}
}
- private static int validateValueChar(CharSequence seq, int state, char character) {
+ private static int validateValueChar(int state, char c, CharSequence seq) {
/*
* State:
* 0: Previous character was neither CR nor LF
* 1: The previous character was CR
* 2: The previous character was LF
*/
- if ((character & HIGHEST_INVALID_VALUE_CHAR_MASK) == 0) {
+ if ((c & HIGHEST_INVALID_VALUE_CHAR_MASK) == 0) {
// Check the absolutely prohibited characters.
- switch (character) {
+ switch (c) {
case 0x0b: // Vertical tab
throw new IllegalArgumentException("a header value contains a prohibited character '\\v': " + seq);
case '\f':
@@ -141,7 +160,7 @@ public class DefaultHttpHeaders extends HttpHeaders {
// Check the CRLF (HT | SP) pattern
switch (state) {
case 0:
- switch (character) {
+ switch (c) {
case '\r':
state = 1;
break;
@@ -151,7 +170,7 @@ public class DefaultHttpHeaders extends HttpHeaders {
}
break;
case 1:
- switch (character) {
+ switch (c) {
case '\n':
state = 2;
break;
@@ -160,7 +179,7 @@ public class DefaultHttpHeaders extends HttpHeaders {
}
break;
case 2:
- switch (character) {
+ switch (c) {
case '\t':
case ' ':
state = 0;
@@ -176,6 +195,24 @@ public class DefaultHttpHeaders extends HttpHeaders {
static class HttpHeadersNameConverter implements NameConverter {
protected final boolean validate;
+ private static final class ValidateNameProcessor implements ByteProcessor {
+ private final CharSequence seq;
+
+ public ValidateNameProcessor(CharSequence seq) {
+ this.seq = seq;
+ }
+
+ @Override
+ public boolean process(byte value) throws Exception {
+ // Check to see if the character is not an ASCII character.
+ if (value < 0) {
+ throw new IllegalArgumentException("a header name cannot contain non-ASCII character: " + seq);
+ }
+ validateNameChar(value, seq);
+ return true;
+ }
+ }
+
HttpHeadersNameConverter(boolean validate) {
this.validate = validate;
}
@@ -194,43 +231,33 @@ public class DefaultHttpHeaders extends HttpHeaders {
}
private static void validateName(AsciiString name) {
- // Go through each characters in the name
- final int start = name.arrayOffset();
- final int end = start + name.length();
- final byte[] array = name.array();
- for (int index = start; index < end; index ++) {
- byte b = array[index];
-
- // Check to see if the character is not an ASCII character
- if (b < 0) {
- throw new IllegalArgumentException("a header name cannot contain non-ASCII characters: " + name);
- }
-
- // Check for prohibited characters.
- validateNameChar(name, b);
+ try {
+ name.forEachByte(new ValidateNameProcessor(name));
+ } catch (Throwable t) {
+ PlatformDependent.throwException(t);
}
}
private static void validateName(CharSequence name) {
- // Go through each characters in the name
+ // Go through each characters in the name.
for (int index = 0; index < name.length(); index++) {
- char character = name.charAt(index);
+ char c = name.charAt(index);
- // Check to see if the character is not an ASCII character
- if (character > 127) {
+ // Check to see if the character is not an ASCII character.
+ if (c > 127) {
throw new IllegalArgumentException("a header name cannot contain non-ASCII characters: " + name);
}
- // Check for prohibited characters
- validateNameChar(name, character);
+ // Check for prohibited characters.
+ validateNameChar(c, name);
}
}
- private static void validateNameChar(CharSequence name, int character) {
+ private static void validateNameChar(int character, CharSequence seq) {
if ((character & HIGHEST_INVALID_NAME_CHAR_MASK) == 0 && LOOKUP_TABLE[character] != 0) {
throw new IllegalArgumentException(
"a header name cannot contain the following prohibited characters: =,;: \\t\\r\\n\\v\\f: " +
- name);
+ seq);
}
}
}
diff --git a/codec-http/src/main/java/io/netty/handler/codec/http/DefaultHttpResponse.java b/codec-http/src/main/java/io/netty/handler/codec/http/DefaultHttpResponse.java
index a95673bf72..85117c77e4 100644
--- a/codec-http/src/main/java/io/netty/handler/codec/http/DefaultHttpResponse.java
+++ b/codec-http/src/main/java/io/netty/handler/codec/http/DefaultHttpResponse.java
@@ -15,7 +15,6 @@
*/
package io.netty.handler.codec.http;
-import io.netty.util.internal.StringUtil;
/**
* The default {@link HttpResponse} implementation.
diff --git a/codec-http/src/main/java/io/netty/handler/codec/http/HttpClientUpgradeHandler.java b/codec-http/src/main/java/io/netty/handler/codec/http/HttpClientUpgradeHandler.java
index b99d55fb77..75c9d5d056 100644
--- a/codec-http/src/main/java/io/netty/handler/codec/http/HttpClientUpgradeHandler.java
+++ b/codec-http/src/main/java/io/netty/handler/codec/http/HttpClientUpgradeHandler.java
@@ -17,7 +17,7 @@ package io.netty.handler.codec.http;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelOutboundHandler;
import io.netty.channel.ChannelPromise;
-import io.netty.handler.codec.AsciiString;
+import io.netty.util.AsciiString;
import java.net.SocketAddress;
import java.util.Collection;
diff --git a/codec-http/src/main/java/io/netty/handler/codec/http/HttpHeaderNames.java b/codec-http/src/main/java/io/netty/handler/codec/http/HttpHeaderNames.java
index a79fafebb6..5a6a024606 100644
--- a/codec-http/src/main/java/io/netty/handler/codec/http/HttpHeaderNames.java
+++ b/codec-http/src/main/java/io/netty/handler/codec/http/HttpHeaderNames.java
@@ -16,7 +16,7 @@
package io.netty.handler.codec.http;
-import io.netty.handler.codec.AsciiString;
+import io.netty.util.AsciiString;
/**
* Standard HTTP header names.
diff --git a/codec-http/src/main/java/io/netty/handler/codec/http/HttpHeaderValues.java b/codec-http/src/main/java/io/netty/handler/codec/http/HttpHeaderValues.java
index ce4534337b..f2d1c91a9f 100644
--- a/codec-http/src/main/java/io/netty/handler/codec/http/HttpHeaderValues.java
+++ b/codec-http/src/main/java/io/netty/handler/codec/http/HttpHeaderValues.java
@@ -16,7 +16,7 @@
package io.netty.handler.codec.http;
-import io.netty.handler.codec.AsciiString;
+import io.netty.util.AsciiString;
/**
* Standard HTTP header values.
diff --git a/codec-http/src/main/java/io/netty/handler/codec/http/HttpHeaders.java b/codec-http/src/main/java/io/netty/handler/codec/http/HttpHeaders.java
index c33e8ce2da..a1486b16f5 100644
--- a/codec-http/src/main/java/io/netty/handler/codec/http/HttpHeaders.java
+++ b/codec-http/src/main/java/io/netty/handler/codec/http/HttpHeaders.java
@@ -16,8 +16,9 @@
package io.netty.handler.codec.http;
import io.netty.buffer.ByteBuf;
-import io.netty.handler.codec.AsciiString;
+import io.netty.buffer.ByteBufUtil;
import io.netty.handler.codec.Headers.EntryVisitor;
+import io.netty.util.AsciiString;
import io.netty.util.internal.PlatformDependent;
import java.text.ParseException;
@@ -1283,7 +1284,7 @@ public abstract class HttpHeaders implements Iterable>
@Deprecated
public static void encodeAscii(CharSequence seq, ByteBuf buf) {
if (seq instanceof AsciiString) {
- ((AsciiString) seq).copy(0, buf, seq.length());
+ ByteBufUtil.copy((AsciiString) seq, 0, buf, seq.length());
} else {
encodeAscii0(seq, buf);
}
diff --git a/codec-http/src/main/java/io/netty/handler/codec/http/HttpHeadersEncoder.java b/codec-http/src/main/java/io/netty/handler/codec/http/HttpHeadersEncoder.java
index 6e2e344ec9..559c6f3ecb 100644
--- a/codec-http/src/main/java/io/netty/handler/codec/http/HttpHeadersEncoder.java
+++ b/codec-http/src/main/java/io/netty/handler/codec/http/HttpHeadersEncoder.java
@@ -17,8 +17,9 @@
package io.netty.handler.codec.http;
import io.netty.buffer.ByteBuf;
-import io.netty.handler.codec.AsciiString;
+import io.netty.buffer.ByteBufUtil;
import io.netty.handler.codec.TextHeaders.EntryVisitor;
+import io.netty.util.AsciiString;
import java.util.Map.Entry;
@@ -61,7 +62,7 @@ final class HttpHeadersEncoder implements EntryVisitor {
}
private static void writeAsciiString(ByteBuf buf, int offset, AsciiString value, int valueLen) {
- value.copy(0, buf, offset, valueLen);
+ ByteBufUtil.copy(value, 0, buf, offset, valueLen);
}
private static void writeCharSequence(ByteBuf buf, int offset, CharSequence value, int valueLen) {
diff --git a/codec-http/src/main/java/io/netty/handler/codec/http/HttpObjectDecoder.java b/codec-http/src/main/java/io/netty/handler/codec/http/HttpObjectDecoder.java
index 54ecd46e79..405b43d8d9 100644
--- a/codec-http/src/main/java/io/netty/handler/codec/http/HttpObjectDecoder.java
+++ b/codec-http/src/main/java/io/netty/handler/codec/http/HttpObjectDecoder.java
@@ -16,13 +16,13 @@
package io.netty.handler.codec.http;
import io.netty.buffer.ByteBuf;
-import io.netty.buffer.ByteBufProcessor;
import io.netty.buffer.Unpooled;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelPipeline;
import io.netty.handler.codec.ByteToMessageDecoder;
import io.netty.handler.codec.DecoderResult;
import io.netty.handler.codec.TooLongFrameException;
+import io.netty.util.ByteProcessor;
import io.netty.util.internal.AppendableCharSequence;
import java.util.List;
@@ -734,7 +734,7 @@ public abstract class HttpObjectDecoder extends ByteToMessageDecoder {
return result;
}
- private static class HeaderParser implements ByteBufProcessor {
+ private static class HeaderParser implements ByteProcessor {
private final AppendableCharSequence seq;
private final int maxLength;
private int size;
diff --git a/codec-http/src/main/java/io/netty/handler/codec/http/HttpResponseStatus.java b/codec-http/src/main/java/io/netty/handler/codec/http/HttpResponseStatus.java
index 5a6c08297d..acf98b3aa4 100644
--- a/codec-http/src/main/java/io/netty/handler/codec/http/HttpResponseStatus.java
+++ b/codec-http/src/main/java/io/netty/handler/codec/http/HttpResponseStatus.java
@@ -15,12 +15,13 @@
*/
package io.netty.handler.codec.http;
+import static io.netty.handler.codec.http.HttpConstants.SP;
import io.netty.buffer.ByteBuf;
-import io.netty.handler.codec.AsciiString;
+import io.netty.util.AsciiString;
+import io.netty.util.ByteProcessor;
+import io.netty.util.ByteString;
import io.netty.util.CharsetUtil;
-import static io.netty.handler.codec.http.HttpConstants.*;
-
/**
* The response code and its description of HTTP or its derived protocols, such as
* RTSP and
@@ -468,6 +469,85 @@ public class HttpResponseStatus implements Comparable {
}
}
+ private static final class HttpStatusLineProcessor implements ByteProcessor {
+ private static final byte ASCII_SPACE = (byte) ' ';
+ private final ByteString string;
+ private int i;
+ /**
+ * 0 = New or havn't seen {@link ASCII_SPACE}.
+ * 1 = Last byte was {@link ASCII_SPACE}.
+ * 2 = Terminal State. Processed the byte after {@link ASCII_SPACE}, and parsed the status line.
+ * 3 = Terminal State. There was no byte after {@link ASCII_SPACE} but status has been parsed with what we saw.
+ */
+ private int state;
+ private HttpResponseStatus status;
+
+ public HttpStatusLineProcessor(ByteString string) {
+ this.string = string;
+ }
+
+ @Override
+ public boolean process(byte value) {
+ switch (state) {
+ case 0:
+ if (value == ASCII_SPACE) {
+ state = 1;
+ }
+ break;
+ case 1:
+ parseStatus(i);
+ state = 2;
+ return false;
+ default:
+ break;
+ }
+ ++i;
+ return true;
+ }
+
+ private void parseStatus(int codeEnd) {
+ int code = string.parseAsciiInt(0, codeEnd);
+ status = valueOf(code);
+ if (codeEnd < string.length()) {
+ String actualReason = string.toString(codeEnd + 1, string.length());
+ if (!status.reasonPhrase().equals(actualReason)) {
+ status = new HttpResponseStatus(code, actualReason);
+ }
+ }
+ }
+
+ public HttpResponseStatus status() {
+ if (state <= 1) {
+ parseStatus(string.length());
+ state = 3;
+ }
+ return status;
+ }
+ }
+
+ /**
+ * Parses the specified HTTP status line into a {@link HttpResponseStatus}. The expected formats of the line are:
+ *
+ * - {@code statusCode} (e.g. 200)
+ * - {@code statusCode} {@code reasonPhrase} (e.g. 404 Not Found)
+ *
+ *
+ * @throws IllegalArgumentException if the specified status line is malformed
+ */
+ public static HttpResponseStatus parseLine(ByteString line) {
+ try {
+ HttpStatusLineProcessor processor = new HttpStatusLineProcessor(line);
+ line.forEachByte(processor);
+ HttpResponseStatus status = processor.status();
+ if (status == null) {
+ throw new IllegalArgumentException("unable to get status after parsing input");
+ }
+ return status;
+ } catch (Exception e) {
+ throw new IllegalArgumentException("malformed status line: " + line, e);
+ }
+ }
+
private final int code;
private final AsciiString codeAsText;
private HttpStatusClass codeClass;
diff --git a/codec-http/src/main/java/io/netty/handler/codec/http/HttpServerUpgradeHandler.java b/codec-http/src/main/java/io/netty/handler/codec/http/HttpServerUpgradeHandler.java
index b5c421c097..620e7df096 100644
--- a/codec-http/src/main/java/io/netty/handler/codec/http/HttpServerUpgradeHandler.java
+++ b/codec-http/src/main/java/io/netty/handler/codec/http/HttpServerUpgradeHandler.java
@@ -17,7 +17,7 @@ package io.netty.handler.codec.http;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelFutureListener;
import io.netty.channel.ChannelHandlerContext;
-import io.netty.handler.codec.AsciiString;
+import io.netty.util.AsciiString;
import io.netty.util.ReferenceCountUtil;
import io.netty.util.ReferenceCounted;
diff --git a/codec-http/src/main/java/io/netty/handler/codec/http/HttpStatusClass.java b/codec-http/src/main/java/io/netty/handler/codec/http/HttpStatusClass.java
index 62d9092fb4..9f57e18984 100644
--- a/codec-http/src/main/java/io/netty/handler/codec/http/HttpStatusClass.java
+++ b/codec-http/src/main/java/io/netty/handler/codec/http/HttpStatusClass.java
@@ -16,7 +16,7 @@
package io.netty.handler.codec.http;
-import io.netty.handler.codec.AsciiString;
+import io.netty.util.AsciiString;
/**
* The class of HTTP status.
diff --git a/codec-http/src/main/java/io/netty/handler/codec/http/websocketx/Utf8Validator.java b/codec-http/src/main/java/io/netty/handler/codec/http/websocketx/Utf8Validator.java
index d4a612fcbf..3a377e7c5b 100644
--- a/codec-http/src/main/java/io/netty/handler/codec/http/websocketx/Utf8Validator.java
+++ b/codec-http/src/main/java/io/netty/handler/codec/http/websocketx/Utf8Validator.java
@@ -36,13 +36,13 @@
package io.netty.handler.codec.http.websocketx;
import io.netty.buffer.ByteBuf;
-import io.netty.buffer.ByteBufProcessor;
import io.netty.handler.codec.CorruptedFrameException;
+import io.netty.util.ByteProcessor;
/**
* Checks UTF8 bytes for validity
*/
-final class Utf8Validator implements ByteBufProcessor {
+final class Utf8Validator implements ByteProcessor {
private static final int UTF8_ACCEPT = 0;
private static final int UTF8_REJECT = 12;
diff --git a/codec-http/src/main/java/io/netty/handler/codec/http/websocketx/WebSocketClientHandshaker00.java b/codec-http/src/main/java/io/netty/handler/codec/http/websocketx/WebSocketClientHandshaker00.java
index 02db5549cc..126d590ab8 100644
--- a/codec-http/src/main/java/io/netty/handler/codec/http/websocketx/WebSocketClientHandshaker00.java
+++ b/codec-http/src/main/java/io/netty/handler/codec/http/websocketx/WebSocketClientHandshaker00.java
@@ -17,7 +17,6 @@ package io.netty.handler.codec.http.websocketx;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
-import io.netty.handler.codec.AsciiString;
import io.netty.handler.codec.http.DefaultFullHttpRequest;
import io.netty.handler.codec.http.FullHttpRequest;
import io.netty.handler.codec.http.FullHttpResponse;
@@ -27,6 +26,7 @@ import io.netty.handler.codec.http.HttpHeaders;
import io.netty.handler.codec.http.HttpMethod;
import io.netty.handler.codec.http.HttpResponseStatus;
import io.netty.handler.codec.http.HttpVersion;
+import io.netty.util.AsciiString;
import java.net.URI;
import java.nio.ByteBuffer;
diff --git a/codec-http/src/main/java/io/netty/handler/codec/rtsp/RtspHeaderNames.java b/codec-http/src/main/java/io/netty/handler/codec/rtsp/RtspHeaderNames.java
index 5ab154101b..e42019bc57 100644
--- a/codec-http/src/main/java/io/netty/handler/codec/rtsp/RtspHeaderNames.java
+++ b/codec-http/src/main/java/io/netty/handler/codec/rtsp/RtspHeaderNames.java
@@ -16,8 +16,8 @@
package io.netty.handler.codec.rtsp;
-import io.netty.handler.codec.AsciiString;
import io.netty.handler.codec.http.HttpHeaderNames;
+import io.netty.util.AsciiString;
/**
* Standard RTSP header names.
diff --git a/codec-http/src/main/java/io/netty/handler/codec/rtsp/RtspHeaderValues.java b/codec-http/src/main/java/io/netty/handler/codec/rtsp/RtspHeaderValues.java
index 86551e6963..d0ba393635 100644
--- a/codec-http/src/main/java/io/netty/handler/codec/rtsp/RtspHeaderValues.java
+++ b/codec-http/src/main/java/io/netty/handler/codec/rtsp/RtspHeaderValues.java
@@ -16,8 +16,8 @@
package io.netty.handler.codec.rtsp;
-import io.netty.handler.codec.AsciiString;
import io.netty.handler.codec.http.HttpHeaderValues;
+import io.netty.util.AsciiString;
/**
* Standard RTSP header names.
diff --git a/codec-http/src/main/java/io/netty/handler/codec/spdy/DefaultSpdyHeaders.java b/codec-http/src/main/java/io/netty/handler/codec/spdy/DefaultSpdyHeaders.java
index 978e1a5a3f..53c00b087a 100644
--- a/codec-http/src/main/java/io/netty/handler/codec/spdy/DefaultSpdyHeaders.java
+++ b/codec-http/src/main/java/io/netty/handler/codec/spdy/DefaultSpdyHeaders.java
@@ -15,10 +15,10 @@
*/
package io.netty.handler.codec.spdy;
-import io.netty.handler.codec.AsciiString;
import io.netty.handler.codec.DefaultTextHeaders;
import io.netty.handler.codec.Headers;
import io.netty.handler.codec.TextHeaders;
+import io.netty.util.AsciiString;
import java.util.Locale;
diff --git a/codec-http/src/main/java/io/netty/handler/codec/spdy/SpdyHeaderBlockRawEncoder.java b/codec-http/src/main/java/io/netty/handler/codec/spdy/SpdyHeaderBlockRawEncoder.java
index a5a5692541..0b93fa28c4 100644
--- a/codec-http/src/main/java/io/netty/handler/codec/spdy/SpdyHeaderBlockRawEncoder.java
+++ b/codec-http/src/main/java/io/netty/handler/codec/spdy/SpdyHeaderBlockRawEncoder.java
@@ -18,8 +18,10 @@ package io.netty.handler.codec.spdy;
import static io.netty.handler.codec.spdy.SpdyCodecUtil.SPDY_MAX_NV_LENGTH;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.ByteBufAllocator;
+import io.netty.buffer.ByteBufUtil;
import io.netty.buffer.Unpooled;
-import io.netty.handler.codec.AsciiString;
+import io.netty.util.AsciiString;
+import io.netty.util.ByteString;
import io.netty.util.CharsetUtil;
import java.util.Set;
@@ -57,18 +59,20 @@ public class SpdyHeaderBlockRawEncoder extends SpdyHeaderBlockEncoder {
ByteBuf headerBlock = alloc.heapBuffer();
writeLengthField(headerBlock, numHeaders);
for (CharSequence name: names) {
- byte[] nameBytes = AsciiString.getBytes(name, CharsetUtil.UTF_8);
- writeLengthField(headerBlock, nameBytes.length);
- headerBlock.writeBytes(nameBytes);
+ final ByteString nameBytes = new ByteString(name, CharsetUtil.UTF_8);
+ int length = nameBytes.length();
+ writeLengthField(headerBlock, length);
+ ByteBufUtil.copy(nameBytes, 0, headerBlock, length);
int savedIndex = headerBlock.writerIndex();
int valueLength = 0;
writeLengthField(headerBlock, valueLength);
for (CharSequence value: frame.headers().getAll(name)) {
- byte[] valueBytes = AsciiString.getBytes(value, CharsetUtil.UTF_8);
- if (valueBytes.length > 0) {
- headerBlock.writeBytes(valueBytes);
+ final ByteString valueBytes = new ByteString(value, CharsetUtil.UTF_8);
+ length = valueBytes.length();
+ if (length > 0) {
+ ByteBufUtil.copy(valueBytes, 0, headerBlock, length);
headerBlock.writeByte(0);
- valueLength += valueBytes.length + 1;
+ valueLength += length + 1;
}
}
if (valueLength != 0) {
diff --git a/codec-http/src/main/java/io/netty/handler/codec/spdy/SpdyHeaders.java b/codec-http/src/main/java/io/netty/handler/codec/spdy/SpdyHeaders.java
index 44a4d7d94b..e82fccef2d 100644
--- a/codec-http/src/main/java/io/netty/handler/codec/spdy/SpdyHeaders.java
+++ b/codec-http/src/main/java/io/netty/handler/codec/spdy/SpdyHeaders.java
@@ -15,8 +15,8 @@
*/
package io.netty.handler.codec.spdy;
-import io.netty.handler.codec.AsciiString;
import io.netty.handler.codec.TextHeaders;
+import io.netty.util.AsciiString;
/**
* Provides the constants for the standard SPDY HTTP header names and commonly
diff --git a/codec-http/src/main/java/io/netty/handler/codec/spdy/SpdyHttpHeaders.java b/codec-http/src/main/java/io/netty/handler/codec/spdy/SpdyHttpHeaders.java
index bd9d11b2c3..a3678e0eb8 100644
--- a/codec-http/src/main/java/io/netty/handler/codec/spdy/SpdyHttpHeaders.java
+++ b/codec-http/src/main/java/io/netty/handler/codec/spdy/SpdyHttpHeaders.java
@@ -15,7 +15,7 @@
*/
package io.netty.handler.codec.spdy;
-import io.netty.handler.codec.AsciiString;
+import io.netty.util.AsciiString;
/**
* Provides the constants for the header names and the utility methods
diff --git a/codec-http/src/test/java/io/netty/handler/codec/http/HttpHeadersTest.java b/codec-http/src/test/java/io/netty/handler/codec/http/HttpHeadersTest.java
index dbf20b2a84..7fa415113b 100644
--- a/codec-http/src/test/java/io/netty/handler/codec/http/HttpHeadersTest.java
+++ b/codec-http/src/test/java/io/netty/handler/codec/http/HttpHeadersTest.java
@@ -15,7 +15,8 @@
*/
package io.netty.handler.codec.http;
-import io.netty.handler.codec.AsciiString;
+import io.netty.util.AsciiString;
+
import org.junit.Test;
import java.util.List;
diff --git a/codec-http2/src/main/java/io/netty/handler/codec/http2/CompressorHttp2ConnectionEncoder.java b/codec-http2/src/main/java/io/netty/handler/codec/http2/CompressorHttp2ConnectionEncoder.java
index 4d91377550..609a39474d 100644
--- a/codec-http2/src/main/java/io/netty/handler/codec/http2/CompressorHttp2ConnectionEncoder.java
+++ b/codec-http2/src/main/java/io/netty/handler/codec/http2/CompressorHttp2ConnectionEncoder.java
@@ -28,10 +28,10 @@ import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelPromise;
import io.netty.channel.ChannelPromiseAggregator;
import io.netty.channel.embedded.EmbeddedChannel;
-import io.netty.handler.codec.AsciiString;
import io.netty.handler.codec.ByteToMessageDecoder;
import io.netty.handler.codec.compression.ZlibCodecFactory;
import io.netty.handler.codec.compression.ZlibWrapper;
+import io.netty.util.ByteString;
/**
* A decorating HTTP2 encoder that will compress data frames according to the {@code content-encoding} header for each
@@ -170,11 +170,11 @@ public class CompressorHttp2ConnectionEncoder extends DecoratingHttp2ConnectionE
* (alternatively, you can throw a {@link Http2Exception} to block unknown encoding).
* @throws Http2Exception If the specified encoding is not not supported and warrants an exception
*/
- protected EmbeddedChannel newContentCompressor(AsciiString contentEncoding) throws Http2Exception {
- if (GZIP.equalsIgnoreCase(contentEncoding) || X_GZIP.equalsIgnoreCase(contentEncoding)) {
+ protected EmbeddedChannel newContentCompressor(ByteString contentEncoding) throws Http2Exception {
+ if (GZIP.equals(contentEncoding) || X_GZIP.equals(contentEncoding)) {
return newCompressionChannel(ZlibWrapper.GZIP);
}
- if (DEFLATE.equalsIgnoreCase(contentEncoding) || X_DEFLATE.equalsIgnoreCase(contentEncoding)) {
+ if (DEFLATE.equals(contentEncoding) || X_DEFLATE.equals(contentEncoding)) {
return newCompressionChannel(ZlibWrapper.ZLIB);
}
// 'identity' or unsupported
@@ -189,7 +189,7 @@ public class CompressorHttp2ConnectionEncoder extends DecoratingHttp2ConnectionE
* @return the expected content encoding of the new content.
* @throws Http2Exception if the {@code contentEncoding} is not supported and warrants an exception
*/
- protected AsciiString getTargetContentEncoding(AsciiString contentEncoding) throws Http2Exception {
+ protected ByteString getTargetContentEncoding(ByteString contentEncoding) throws Http2Exception {
return contentEncoding;
}
@@ -219,7 +219,7 @@ public class CompressorHttp2ConnectionEncoder extends DecoratingHttp2ConnectionE
EmbeddedChannel compressor = stream.getProperty(CompressorHttp2ConnectionEncoder.class);
if (compressor == null) {
if (!endOfStream) {
- AsciiString encoding = headers.get(CONTENT_ENCODING);
+ ByteString encoding = headers.get(CONTENT_ENCODING);
if (encoding == null) {
encoding = IDENTITY;
}
@@ -227,8 +227,8 @@ public class CompressorHttp2ConnectionEncoder extends DecoratingHttp2ConnectionE
compressor = newContentCompressor(encoding);
if (compressor != null) {
stream.setProperty(CompressorHttp2ConnectionEncoder.class, compressor);
- AsciiString targetContentEncoding = getTargetContentEncoding(encoding);
- if (IDENTITY.equalsIgnoreCase(targetContentEncoding)) {
+ ByteString targetContentEncoding = getTargetContentEncoding(encoding);
+ if (IDENTITY.equals(targetContentEncoding)) {
headers.remove(CONTENT_ENCODING);
} else {
headers.set(CONTENT_ENCODING, targetContentEncoding);
diff --git a/codec-http2/src/main/java/io/netty/handler/codec/http2/DefaultHttp2Headers.java b/codec-http2/src/main/java/io/netty/handler/codec/http2/DefaultHttp2Headers.java
index 71f802af37..1b515de968 100644
--- a/codec-http2/src/main/java/io/netty/handler/codec/http2/DefaultHttp2Headers.java
+++ b/codec-http2/src/main/java/io/netty/handler/codec/http2/DefaultHttp2Headers.java
@@ -14,11 +14,63 @@
*/
package io.netty.handler.codec.http2;
-import io.netty.handler.codec.AsciiString;
+import static io.netty.util.internal.StringUtil.UPPER_CASE_TO_LOWER_CASE_ASCII_OFFSET;
import io.netty.handler.codec.BinaryHeaders;
import io.netty.handler.codec.DefaultBinaryHeaders;
+import io.netty.util.AsciiString;
+import io.netty.util.ByteProcessor;
+import io.netty.util.ByteString;
+import io.netty.util.internal.PlatformDependent;
public class DefaultHttp2Headers extends DefaultBinaryHeaders implements Http2Headers {
+ private static final ByteProcessor HTTP2_ASCII_UPPERCASE_PROCESSOR = new ByteProcessor() {
+ @Override
+ public boolean process(byte value) throws Exception {
+ return value < 'A' || value > 'Z';
+ }
+ };
+
+ private static final class Http2AsciiToLowerCaseConverter implements ByteProcessor {
+ private final byte[] result;
+ private int i;
+
+ public Http2AsciiToLowerCaseConverter(int length) {
+ result = new byte[length];
+ }
+
+ @Override
+ public boolean process(byte value) throws Exception {
+ result[i++] = (value >= 'A' && value <= 'Z')
+ ? (byte) (value + UPPER_CASE_TO_LOWER_CASE_ASCII_OFFSET) : value;
+ return true;
+ }
+
+ public byte[] result() {
+ return result;
+ }
+ };
+
+ private static final NameConverter HTTP2_ASCII_TO_LOWER_CONVERTER = new NameConverter() {
+ @Override
+ public ByteString convertName(ByteString name) {
+ if (name instanceof AsciiString) {
+ return ((AsciiString) name).toLowerCase();
+ }
+
+ try {
+ if (name.forEachByte(HTTP2_ASCII_UPPERCASE_PROCESSOR) == -1) {
+ return name;
+ }
+
+ Http2AsciiToLowerCaseConverter converter = new Http2AsciiToLowerCaseConverter(name.length());
+ name.forEachByte(converter);
+ return new ByteString(converter.result(), false);
+ } catch (Exception e) {
+ PlatformDependent.throwException(e);
+ return null;
+ }
+ }
+ };
/**
* Creates an instance that will convert all header names to lowercase.
@@ -41,95 +93,95 @@ public class DefaultHttp2Headers extends DefaultBinaryHeaders implements Http2He
* @param forceKeyToLower if @{code false} no header name conversion will be performed
*/
public DefaultHttp2Headers(boolean forceKeyToLower) {
- super(forceKeyToLower);
+ super(forceKeyToLower ? HTTP2_ASCII_TO_LOWER_CONVERTER : IDENTITY_NAME_CONVERTER);
}
@Override
- public Http2Headers add(AsciiString name, AsciiString value) {
+ public Http2Headers add(ByteString name, ByteString value) {
super.add(name, value);
return this;
}
@Override
- public Http2Headers add(AsciiString name, Iterable extends AsciiString> values) {
+ public Http2Headers add(ByteString name, Iterable extends ByteString> values) {
super.add(name, values);
return this;
}
@Override
- public Http2Headers add(AsciiString name, AsciiString... values) {
+ public Http2Headers add(ByteString name, ByteString... values) {
super.add(name, values);
return this;
}
@Override
- public Http2Headers addObject(AsciiString name, Object value) {
+ public Http2Headers addObject(ByteString name, Object value) {
super.addObject(name, value);
return this;
}
@Override
- public Http2Headers addObject(AsciiString name, Iterable> values) {
+ public Http2Headers addObject(ByteString name, Iterable> values) {
super.addObject(name, values);
return this;
}
@Override
- public Http2Headers addObject(AsciiString name, Object... values) {
+ public Http2Headers addObject(ByteString name, Object... values) {
super.addObject(name, values);
return this;
}
@Override
- public Http2Headers addBoolean(AsciiString name, boolean value) {
+ public Http2Headers addBoolean(ByteString name, boolean value) {
super.addBoolean(name, value);
return this;
}
@Override
- public Http2Headers addChar(AsciiString name, char value) {
+ public Http2Headers addChar(ByteString name, char value) {
super.addChar(name, value);
return this;
}
@Override
- public Http2Headers addByte(AsciiString name, byte value) {
+ public Http2Headers addByte(ByteString name, byte value) {
super.addByte(name, value);
return this;
}
@Override
- public Http2Headers addShort(AsciiString name, short value) {
+ public Http2Headers addShort(ByteString name, short value) {
super.addShort(name, value);
return this;
}
@Override
- public Http2Headers addInt(AsciiString name, int value) {
+ public Http2Headers addInt(ByteString name, int value) {
super.addInt(name, value);
return this;
}
@Override
- public Http2Headers addLong(AsciiString name, long value) {
+ public Http2Headers addLong(ByteString name, long value) {
super.addLong(name, value);
return this;
}
@Override
- public Http2Headers addFloat(AsciiString name, float value) {
+ public Http2Headers addFloat(ByteString name, float value) {
super.addFloat(name, value);
return this;
}
@Override
- public Http2Headers addDouble(AsciiString name, double value) {
+ public Http2Headers addDouble(ByteString name, double value) {
super.addDouble(name, value);
return this;
}
@Override
- public Http2Headers addTimeMillis(AsciiString name, long value) {
+ public Http2Headers addTimeMillis(ByteString name, long value) {
super.addTimeMillis(name, value);
return this;
}
@@ -141,91 +193,91 @@ public class DefaultHttp2Headers extends DefaultBinaryHeaders implements Http2He
}
@Override
- public Http2Headers set(AsciiString name, AsciiString value) {
+ public Http2Headers set(ByteString name, ByteString value) {
super.set(name, value);
return this;
}
@Override
- public Http2Headers set(AsciiString name, Iterable extends AsciiString> values) {
+ public Http2Headers set(ByteString name, Iterable extends ByteString> values) {
super.set(name, values);
return this;
}
@Override
- public Http2Headers set(AsciiString name, AsciiString... values) {
+ public Http2Headers set(ByteString name, ByteString... values) {
super.set(name, values);
return this;
}
@Override
- public Http2Headers setObject(AsciiString name, Object value) {
+ public Http2Headers setObject(ByteString name, Object value) {
super.setObject(name, value);
return this;
}
@Override
- public Http2Headers setObject(AsciiString name, Iterable> values) {
+ public Http2Headers setObject(ByteString name, Iterable> values) {
super.setObject(name, values);
return this;
}
@Override
- public Http2Headers setObject(AsciiString name, Object... values) {
+ public Http2Headers setObject(ByteString name, Object... values) {
super.setObject(name, values);
return this;
}
@Override
- public Http2Headers setBoolean(AsciiString name, boolean value) {
+ public Http2Headers setBoolean(ByteString name, boolean value) {
super.setBoolean(name, value);
return this;
}
@Override
- public Http2Headers setChar(AsciiString name, char value) {
+ public Http2Headers setChar(ByteString name, char value) {
super.setChar(name, value);
return this;
}
@Override
- public Http2Headers setByte(AsciiString name, byte value) {
+ public Http2Headers setByte(ByteString name, byte value) {
super.setByte(name, value);
return this;
}
@Override
- public Http2Headers setShort(AsciiString name, short value) {
+ public Http2Headers setShort(ByteString name, short value) {
super.setShort(name, value);
return this;
}
@Override
- public Http2Headers setInt(AsciiString name, int value) {
+ public Http2Headers setInt(ByteString name, int value) {
super.setInt(name, value);
return this;
}
@Override
- public Http2Headers setLong(AsciiString name, long value) {
+ public Http2Headers setLong(ByteString name, long value) {
super.setLong(name, value);
return this;
}
@Override
- public Http2Headers setFloat(AsciiString name, float value) {
+ public Http2Headers setFloat(ByteString name, float value) {
super.setFloat(name, value);
return this;
}
@Override
- public Http2Headers setDouble(AsciiString name, double value) {
+ public Http2Headers setDouble(ByteString name, double value) {
super.setDouble(name, value);
return this;
}
@Override
- public Http2Headers setTimeMillis(AsciiString name, long value) {
+ public Http2Headers setTimeMillis(ByteString name, long value) {
super.setTimeMillis(name, value);
return this;
}
@@ -249,57 +301,57 @@ public class DefaultHttp2Headers extends DefaultBinaryHeaders implements Http2He
}
@Override
- public Http2Headers method(AsciiString value) {
+ public Http2Headers method(ByteString value) {
set(PseudoHeaderName.METHOD.value(), value);
return this;
}
@Override
- public Http2Headers scheme(AsciiString value) {
+ public Http2Headers scheme(ByteString value) {
set(PseudoHeaderName.SCHEME.value(), value);
return this;
}
@Override
- public Http2Headers authority(AsciiString value) {
+ public Http2Headers authority(ByteString value) {
set(PseudoHeaderName.AUTHORITY.value(), value);
return this;
}
@Override
- public Http2Headers path(AsciiString value) {
+ public Http2Headers path(ByteString value) {
set(PseudoHeaderName.PATH.value(), value);
return this;
}
@Override
- public Http2Headers status(AsciiString value) {
+ public Http2Headers status(ByteString value) {
set(PseudoHeaderName.STATUS.value(), value);
return this;
}
@Override
- public AsciiString method() {
+ public ByteString method() {
return get(PseudoHeaderName.METHOD.value());
}
@Override
- public AsciiString scheme() {
+ public ByteString scheme() {
return get(PseudoHeaderName.SCHEME.value());
}
@Override
- public AsciiString authority() {
+ public ByteString authority() {
return get(PseudoHeaderName.AUTHORITY.value());
}
@Override
- public AsciiString path() {
+ public ByteString path() {
return get(PseudoHeaderName.PATH.value());
}
@Override
- public AsciiString status() {
+ public ByteString status() {
return get(PseudoHeaderName.STATUS.value());
}
}
diff --git a/codec-http2/src/main/java/io/netty/handler/codec/http2/DefaultHttp2HeadersDecoder.java b/codec-http2/src/main/java/io/netty/handler/codec/http2/DefaultHttp2HeadersDecoder.java
index 4f4a3b31db..be207263c2 100644
--- a/codec-http2/src/main/java/io/netty/handler/codec/http2/DefaultHttp2HeadersDecoder.java
+++ b/codec-http2/src/main/java/io/netty/handler/codec/http2/DefaultHttp2HeadersDecoder.java
@@ -17,13 +17,13 @@ package io.netty.handler.codec.http2;
import static io.netty.handler.codec.http2.Http2CodecUtil.DEFAULT_HEADER_TABLE_SIZE;
import static io.netty.handler.codec.http2.Http2CodecUtil.DEFAULT_MAX_HEADER_SIZE;
+import static io.netty.handler.codec.http2.Http2Error.COMPRESSION_ERROR;
import static io.netty.handler.codec.http2.Http2Error.INTERNAL_ERROR;
import static io.netty.handler.codec.http2.Http2Error.PROTOCOL_ERROR;
-import static io.netty.handler.codec.http2.Http2Error.COMPRESSION_ERROR;
import static io.netty.handler.codec.http2.Http2Exception.connectionError;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.ByteBufInputStream;
-import io.netty.handler.codec.AsciiString;
+import io.netty.util.ByteString;
import java.io.IOException;
import java.io.InputStream;
@@ -62,7 +62,7 @@ public class DefaultHttp2HeadersDecoder implements Http2HeadersDecoder, Http2Hea
HeaderListener listener = new HeaderListener() {
@Override
public void addHeader(byte[] key, byte[] value, boolean sensitive) {
- headers.add(new AsciiString(key, false), new AsciiString(value, false));
+ headers.add(new ByteString(key, false), new ByteString(value, false));
}
};
diff --git a/codec-http2/src/main/java/io/netty/handler/codec/http2/DefaultHttp2HeadersEncoder.java b/codec-http2/src/main/java/io/netty/handler/codec/http2/DefaultHttp2HeadersEncoder.java
index 114d5e2ad2..b619606cc5 100644
--- a/codec-http2/src/main/java/io/netty/handler/codec/http2/DefaultHttp2HeadersEncoder.java
+++ b/codec-http2/src/main/java/io/netty/handler/codec/http2/DefaultHttp2HeadersEncoder.java
@@ -23,8 +23,8 @@ import static io.netty.handler.codec.http2.Http2Exception.connectionError;
import static io.netty.util.internal.ObjectUtil.checkNotNull;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.ByteBufOutputStream;
-import io.netty.handler.codec.AsciiString;
import io.netty.handler.codec.BinaryHeaders.EntryVisitor;
+import io.netty.util.ByteString;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
@@ -67,8 +67,8 @@ public class DefaultHttp2HeadersEncoder implements Http2HeadersEncoder, Http2Hea
// Write pseudo headers first as required by the HTTP/2 spec.
for (Http2Headers.PseudoHeaderName pseudoHeader : Http2Headers.PseudoHeaderName.values()) {
- AsciiString name = pseudoHeader.value();
- AsciiString value = headers.get(name);
+ ByteString name = pseudoHeader.value();
+ ByteString value = headers.get(name);
if (value != null) {
encodeHeader(name, value, stream);
}
@@ -76,9 +76,9 @@ public class DefaultHttp2HeadersEncoder implements Http2HeadersEncoder, Http2Hea
headers.forEachEntry(new EntryVisitor() {
@Override
- public boolean visit(Entry entry) throws Exception {
- final AsciiString name = entry.getKey();
- final AsciiString value = entry.getValue();
+ public boolean visit(Entry entry) throws Exception {
+ final ByteString name = entry.getKey();
+ final ByteString value = entry.getValue();
if (!Http2Headers.PseudoHeaderName.isPseudoHeader(name)) {
encodeHeader(name, value, stream);
}
@@ -108,7 +108,7 @@ public class DefaultHttp2HeadersEncoder implements Http2HeadersEncoder, Http2Hea
return this;
}
- private void encodeHeader(AsciiString key, AsciiString value, OutputStream stream) throws IOException {
+ private void encodeHeader(ByteString key, ByteString value, OutputStream stream) throws IOException {
encoder.encodeHeader(stream, key.array(), value.array(), sensitivityDetector.isSensitive(key, value));
}
diff --git a/codec-http2/src/main/java/io/netty/handler/codec/http2/DelegatingDecompressorFrameListener.java b/codec-http2/src/main/java/io/netty/handler/codec/http2/DelegatingDecompressorFrameListener.java
index 9cff863d5a..eb8d15c120 100644
--- a/codec-http2/src/main/java/io/netty/handler/codec/http2/DelegatingDecompressorFrameListener.java
+++ b/codec-http2/src/main/java/io/netty/handler/codec/http2/DelegatingDecompressorFrameListener.java
@@ -28,10 +28,10 @@ import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.embedded.EmbeddedChannel;
-import io.netty.handler.codec.AsciiString;
import io.netty.handler.codec.ByteToMessageDecoder;
import io.netty.handler.codec.compression.ZlibCodecFactory;
import io.netty.handler.codec.compression.ZlibWrapper;
+import io.netty.util.ByteString;
/**
* A HTTP2 frame listener that will decompress data frames according to the {@code content-encoding} header for each
@@ -159,13 +159,11 @@ public class DelegatingDecompressorFrameListener extends Http2FrameListenerDecor
* (alternatively, you can throw a {@link Http2Exception} to block unknown encoding).
* @throws Http2Exception If the specified encoding is not not supported and warrants an exception
*/
- protected EmbeddedChannel newContentDecompressor(AsciiString contentEncoding) throws Http2Exception {
- if (GZIP.equalsIgnoreCase(contentEncoding) ||
- X_GZIP.equalsIgnoreCase(contentEncoding)) {
+ protected EmbeddedChannel newContentDecompressor(ByteString contentEncoding) throws Http2Exception {
+ if (GZIP.equals(contentEncoding) || X_GZIP.equals(contentEncoding)) {
return new EmbeddedChannel(ZlibCodecFactory.newZlibDecoder(ZlibWrapper.GZIP));
}
- if (DEFLATE.equalsIgnoreCase(contentEncoding) ||
- X_DEFLATE.equalsIgnoreCase(contentEncoding)) {
+ if (DEFLATE.equals(contentEncoding) || X_DEFLATE.equals(contentEncoding)) {
final ZlibWrapper wrapper = strict ? ZlibWrapper.ZLIB : ZlibWrapper.ZLIB_OR_NONE;
// To be strict, 'deflate' means ZLIB, but some servers were not implemented correctly.
return new EmbeddedChannel(ZlibCodecFactory.newZlibDecoder(wrapper));
@@ -182,7 +180,7 @@ public class DelegatingDecompressorFrameListener extends Http2FrameListenerDecor
* @return the expected content encoding of the new content.
* @throws Http2Exception if the {@code contentEncoding} is not supported and warrants an exception
*/
- protected AsciiString getTargetContentEncoding(@SuppressWarnings("UnusedParameters") AsciiString contentEncoding)
+ protected ByteString getTargetContentEncoding(@SuppressWarnings("UnusedParameters") ByteString contentEncoding)
throws Http2Exception {
return IDENTITY;
}
@@ -205,7 +203,7 @@ public class DelegatingDecompressorFrameListener extends Http2FrameListenerDecor
Http2Decompressor decompressor = decompressor(stream);
if (decompressor == null && !endOfStream) {
// Determine the content encoding.
- AsciiString contentEncoding = headers.get(CONTENT_ENCODING);
+ ByteString contentEncoding = headers.get(CONTENT_ENCODING);
if (contentEncoding == null) {
contentEncoding = IDENTITY;
}
@@ -215,8 +213,8 @@ public class DelegatingDecompressorFrameListener extends Http2FrameListenerDecor
stream.setProperty(Http2Decompressor.class, decompressor);
// Decode the content and remove or replace the existing headers
// so that the message looks like a decoded message.
- AsciiString targetContentEncoding = getTargetContentEncoding(contentEncoding);
- if (IDENTITY.equalsIgnoreCase(targetContentEncoding)) {
+ ByteString targetContentEncoding = getTargetContentEncoding(contentEncoding);
+ if (IDENTITY.equals(targetContentEncoding)) {
headers.remove(CONTENT_ENCODING);
} else {
headers.set(CONTENT_ENCODING, targetContentEncoding);
diff --git a/codec-http2/src/main/java/io/netty/handler/codec/http2/EmptyHttp2Headers.java b/codec-http2/src/main/java/io/netty/handler/codec/http2/EmptyHttp2Headers.java
index 582c7e346a..e08941ba9f 100644
--- a/codec-http2/src/main/java/io/netty/handler/codec/http2/EmptyHttp2Headers.java
+++ b/codec-http2/src/main/java/io/netty/handler/codec/http2/EmptyHttp2Headers.java
@@ -15,9 +15,9 @@
package io.netty.handler.codec.http2;
-import io.netty.handler.codec.AsciiString;
import io.netty.handler.codec.BinaryHeaders;
import io.netty.handler.codec.EmptyBinaryHeaders;
+import io.netty.util.ByteString;
public final class EmptyHttp2Headers extends EmptyBinaryHeaders implements Http2Headers {
public static final EmptyHttp2Headers INSTANCE = new EmptyHttp2Headers();
@@ -26,91 +26,91 @@ public final class EmptyHttp2Headers extends EmptyBinaryHeaders implements Http2
}
@Override
- public Http2Headers add(AsciiString name, AsciiString value) {
+ public Http2Headers add(ByteString name, ByteString value) {
super.add(name, value);
return this;
}
@Override
- public Http2Headers add(AsciiString name, Iterable extends AsciiString> values) {
+ public Http2Headers add(ByteString name, Iterable extends ByteString> values) {
super.add(name, values);
return this;
}
@Override
- public Http2Headers add(AsciiString name, AsciiString... values) {
+ public Http2Headers add(ByteString name, ByteString... values) {
super.add(name, values);
return this;
}
@Override
- public Http2Headers addObject(AsciiString name, Object value) {
+ public Http2Headers addObject(ByteString name, Object value) {
super.addObject(name, value);
return this;
}
@Override
- public Http2Headers addObject(AsciiString name, Iterable> values) {
+ public Http2Headers addObject(ByteString name, Iterable> values) {
super.addObject(name, values);
return this;
}
@Override
- public Http2Headers addObject(AsciiString name, Object... values) {
+ public Http2Headers addObject(ByteString name, Object... values) {
super.addObject(name, values);
return this;
}
@Override
- public Http2Headers addBoolean(AsciiString name, boolean value) {
+ public Http2Headers addBoolean(ByteString name, boolean value) {
super.addBoolean(name, value);
return this;
}
@Override
- public Http2Headers addChar(AsciiString name, char value) {
+ public Http2Headers addChar(ByteString name, char value) {
super.addChar(name, value);
return this;
}
@Override
- public Http2Headers addByte(AsciiString name, byte value) {
+ public Http2Headers addByte(ByteString name, byte value) {
super.addByte(name, value);
return this;
}
@Override
- public Http2Headers addShort(AsciiString name, short value) {
+ public Http2Headers addShort(ByteString name, short value) {
super.addShort(name, value);
return this;
}
@Override
- public Http2Headers addInt(AsciiString name, int value) {
+ public Http2Headers addInt(ByteString name, int value) {
super.addInt(name, value);
return this;
}
@Override
- public Http2Headers addLong(AsciiString name, long value) {
+ public Http2Headers addLong(ByteString name, long value) {
super.addLong(name, value);
return this;
}
@Override
- public Http2Headers addFloat(AsciiString name, float value) {
+ public Http2Headers addFloat(ByteString name, float value) {
super.addFloat(name, value);
return this;
}
@Override
- public Http2Headers addDouble(AsciiString name, double value) {
+ public Http2Headers addDouble(ByteString name, double value) {
super.addDouble(name, value);
return this;
}
@Override
- public Http2Headers addTimeMillis(AsciiString name, long value) {
+ public Http2Headers addTimeMillis(ByteString name, long value) {
super.addTimeMillis(name, value);
return this;
}
@@ -122,91 +122,91 @@ public final class EmptyHttp2Headers extends EmptyBinaryHeaders implements Http2
}
@Override
- public Http2Headers set(AsciiString name, AsciiString value) {
+ public Http2Headers set(ByteString name, ByteString value) {
super.set(name, value);
return this;
}
@Override
- public Http2Headers set(AsciiString name, Iterable extends AsciiString> values) {
+ public Http2Headers set(ByteString name, Iterable extends ByteString> values) {
super.set(name, values);
return this;
}
@Override
- public Http2Headers set(AsciiString name, AsciiString... values) {
+ public Http2Headers set(ByteString name, ByteString... values) {
super.set(name, values);
return this;
}
@Override
- public Http2Headers setObject(AsciiString name, Object value) {
+ public Http2Headers setObject(ByteString name, Object value) {
super.setObject(name, value);
return this;
}
@Override
- public Http2Headers setObject(AsciiString name, Iterable> values) {
+ public Http2Headers setObject(ByteString name, Iterable> values) {
super.setObject(name, values);
return this;
}
@Override
- public Http2Headers setObject(AsciiString name, Object... values) {
+ public Http2Headers setObject(ByteString name, Object... values) {
super.setObject(name, values);
return this;
}
@Override
- public Http2Headers setBoolean(AsciiString name, boolean value) {
+ public Http2Headers setBoolean(ByteString name, boolean value) {
super.setBoolean(name, value);
return this;
}
@Override
- public Http2Headers setChar(AsciiString name, char value) {
+ public Http2Headers setChar(ByteString name, char value) {
super.setChar(name, value);
return this;
}
@Override
- public Http2Headers setByte(AsciiString name, byte value) {
+ public Http2Headers setByte(ByteString name, byte value) {
super.setByte(name, value);
return this;
}
@Override
- public Http2Headers setShort(AsciiString name, short value) {
+ public Http2Headers setShort(ByteString name, short value) {
super.setShort(name, value);
return this;
}
@Override
- public Http2Headers setInt(AsciiString name, int value) {
+ public Http2Headers setInt(ByteString name, int value) {
super.setInt(name, value);
return this;
}
@Override
- public Http2Headers setLong(AsciiString name, long value) {
+ public Http2Headers setLong(ByteString name, long value) {
super.setLong(name, value);
return this;
}
@Override
- public Http2Headers setFloat(AsciiString name, float value) {
+ public Http2Headers setFloat(ByteString name, float value) {
super.setFloat(name, value);
return this;
}
@Override
- public Http2Headers setDouble(AsciiString name, double value) {
+ public Http2Headers setDouble(ByteString name, double value) {
super.setDouble(name, value);
return this;
}
@Override
- public Http2Headers setTimeMillis(AsciiString name, long value) {
+ public Http2Headers setTimeMillis(ByteString name, long value) {
super.setTimeMillis(name, value);
return this;
}
@@ -230,52 +230,52 @@ public final class EmptyHttp2Headers extends EmptyBinaryHeaders implements Http2
}
@Override
- public EmptyHttp2Headers method(AsciiString method) {
+ public EmptyHttp2Headers method(ByteString method) {
throw new UnsupportedOperationException();
}
@Override
- public EmptyHttp2Headers scheme(AsciiString status) {
+ public EmptyHttp2Headers scheme(ByteString status) {
throw new UnsupportedOperationException();
}
@Override
- public EmptyHttp2Headers authority(AsciiString authority) {
+ public EmptyHttp2Headers authority(ByteString authority) {
throw new UnsupportedOperationException();
}
@Override
- public EmptyHttp2Headers path(AsciiString path) {
+ public EmptyHttp2Headers path(ByteString path) {
throw new UnsupportedOperationException();
}
@Override
- public EmptyHttp2Headers status(AsciiString status) {
+ public EmptyHttp2Headers status(ByteString status) {
throw new UnsupportedOperationException();
}
@Override
- public AsciiString method() {
+ public ByteString method() {
return get(PseudoHeaderName.METHOD.value());
}
@Override
- public AsciiString scheme() {
+ public ByteString scheme() {
return get(PseudoHeaderName.SCHEME.value());
}
@Override
- public AsciiString authority() {
+ public ByteString authority() {
return get(PseudoHeaderName.AUTHORITY.value());
}
@Override
- public AsciiString path() {
+ public ByteString path() {
return get(PseudoHeaderName.PATH.value());
}
@Override
- public AsciiString status() {
+ public ByteString status() {
return get(PseudoHeaderName.STATUS.value());
}
}
diff --git a/codec-http2/src/main/java/io/netty/handler/codec/http2/Http2Headers.java b/codec-http2/src/main/java/io/netty/handler/codec/http2/Http2Headers.java
index 7adbfc7891..5b30fc713a 100644
--- a/codec-http2/src/main/java/io/netty/handler/codec/http2/Http2Headers.java
+++ b/codec-http2/src/main/java/io/netty/handler/codec/http2/Http2Headers.java
@@ -15,8 +15,9 @@
package io.netty.handler.codec.http2;
-import io.netty.handler.codec.AsciiString;
import io.netty.handler.codec.BinaryHeaders;
+import io.netty.util.ByteString;
+import io.netty.util.CharsetUtil;
import java.util.HashSet;
import java.util.Set;
@@ -55,8 +56,8 @@ public interface Http2Headers extends BinaryHeaders {
*/
STATUS(":status");
- private final AsciiString value;
- private static final Set PSEUDO_HEADERS = new HashSet();
+ private final ByteString value;
+ private static final Set PSEUDO_HEADERS = new HashSet();
static {
for (PseudoHeaderName pseudoHeader : PseudoHeaderName.values()) {
PSEUDO_HEADERS.add(pseudoHeader.value());
@@ -64,10 +65,10 @@ public interface Http2Headers extends BinaryHeaders {
}
PseudoHeaderName(String value) {
- this.value = new AsciiString(value);
+ this.value = new ByteString(value, CharsetUtil.UTF_8);
}
- public AsciiString value() {
+ public ByteString value() {
// Return a slice so that the buffer gets its own reader index.
return value;
}
@@ -75,103 +76,103 @@ public interface Http2Headers extends BinaryHeaders {
/**
* Indicates whether the given header name is a valid HTTP/2 pseudo header.
*/
- public static boolean isPseudoHeader(AsciiString header) {
+ public static boolean isPseudoHeader(ByteString header) {
return PSEUDO_HEADERS.contains(header);
}
}
@Override
- Http2Headers add(AsciiString name, AsciiString value);
+ Http2Headers add(ByteString name, ByteString value);
@Override
- Http2Headers add(AsciiString name, Iterable extends AsciiString> values);
+ Http2Headers add(ByteString name, Iterable extends ByteString> values);
@Override
- Http2Headers add(AsciiString name, AsciiString... values);
+ Http2Headers add(ByteString name, ByteString... values);
@Override
- Http2Headers addObject(AsciiString name, Object value);
+ Http2Headers addObject(ByteString name, Object value);
@Override
- Http2Headers addObject(AsciiString name, Iterable> values);
+ Http2Headers addObject(ByteString name, Iterable> values);
@Override
- Http2Headers addObject(AsciiString name, Object... values);
+ Http2Headers addObject(ByteString name, Object... values);
@Override
- Http2Headers addBoolean(AsciiString name, boolean value);
+ Http2Headers addBoolean(ByteString name, boolean value);
@Override
- Http2Headers addByte(AsciiString name, byte value);
+ Http2Headers addByte(ByteString name, byte value);
@Override
- Http2Headers addChar(AsciiString name, char value);
+ Http2Headers addChar(ByteString name, char value);
@Override
- Http2Headers addShort(AsciiString name, short value);
+ Http2Headers addShort(ByteString name, short value);
@Override
- Http2Headers addInt(AsciiString name, int value);
+ Http2Headers addInt(ByteString name, int value);
@Override
- Http2Headers addLong(AsciiString name, long value);
+ Http2Headers addLong(ByteString name, long value);
@Override
- Http2Headers addFloat(AsciiString name, float value);
+ Http2Headers addFloat(ByteString name, float value);
@Override
- Http2Headers addDouble(AsciiString name, double value);
+ Http2Headers addDouble(ByteString name, double value);
@Override
- Http2Headers addTimeMillis(AsciiString name, long value);
+ Http2Headers addTimeMillis(ByteString name, long value);
@Override
Http2Headers add(BinaryHeaders headers);
@Override
- Http2Headers set(AsciiString name, AsciiString value);
+ Http2Headers set(ByteString name, ByteString value);
@Override
- Http2Headers set(AsciiString name, Iterable extends AsciiString> values);
+ Http2Headers set(ByteString name, Iterable extends ByteString> values);
@Override
- Http2Headers set(AsciiString name, AsciiString... values);
+ Http2Headers set(ByteString name, ByteString... values);
@Override
- Http2Headers setObject(AsciiString name, Object value);
+ Http2Headers setObject(ByteString name, Object value);
@Override
- Http2Headers setObject(AsciiString name, Iterable> values);
+ Http2Headers setObject(ByteString name, Iterable> values);
@Override
- Http2Headers setObject(AsciiString name, Object... values);
+ Http2Headers setObject(ByteString name, Object... values);
@Override
- Http2Headers setBoolean(AsciiString name, boolean value);
+ Http2Headers setBoolean(ByteString name, boolean value);
@Override
- Http2Headers setByte(AsciiString name, byte value);
+ Http2Headers setByte(ByteString name, byte value);
@Override
- Http2Headers setChar(AsciiString name, char value);
+ Http2Headers setChar(ByteString name, char value);
@Override
- Http2Headers setShort(AsciiString name, short value);
+ Http2Headers setShort(ByteString name, short value);
@Override
- Http2Headers setInt(AsciiString name, int value);
+ Http2Headers setInt(ByteString name, int value);
@Override
- Http2Headers setLong(AsciiString name, long value);
+ Http2Headers setLong(ByteString name, long value);
@Override
- Http2Headers setFloat(AsciiString name, float value);
+ Http2Headers setFloat(ByteString name, float value);
@Override
- Http2Headers setDouble(AsciiString name, double value);
+ Http2Headers setDouble(ByteString name, double value);
@Override
- Http2Headers setTimeMillis(AsciiString name, long value);
+ Http2Headers setTimeMillis(ByteString name, long value);
@Override
Http2Headers set(BinaryHeaders headers);
@@ -185,50 +186,50 @@ public interface Http2Headers extends BinaryHeaders {
/**
* Sets the {@link PseudoHeaderName#METHOD} header or {@code null} if there is no such header
*/
- Http2Headers method(AsciiString value);
+ Http2Headers method(ByteString value);
/**
* Sets the {@link PseudoHeaderName#SCHEME} header if there is no such header
*/
- Http2Headers scheme(AsciiString value);
+ Http2Headers scheme(ByteString value);
/**
* Sets the {@link PseudoHeaderName#AUTHORITY} header or {@code null} if there is no such header
*/
- Http2Headers authority(AsciiString value);
+ Http2Headers authority(ByteString value);
/**
* Sets the {@link PseudoHeaderName#PATH} header or {@code null} if there is no such header
*/
- Http2Headers path(AsciiString value);
+ Http2Headers path(ByteString value);
/**
* Sets the {@link PseudoHeaderName#STATUS} header or {@code null} if there is no such header
*/
- Http2Headers status(AsciiString value);
+ Http2Headers status(ByteString value);
/**
* Gets the {@link PseudoHeaderName#METHOD} header or {@code null} if there is no such header
*/
- AsciiString method();
+ ByteString method();
/**
* Gets the {@link PseudoHeaderName#SCHEME} header or {@code null} if there is no such header
*/
- AsciiString scheme();
+ ByteString scheme();
/**
* Gets the {@link PseudoHeaderName#AUTHORITY} header or {@code null} if there is no such header
*/
- AsciiString authority();
+ ByteString authority();
/**
* Gets the {@link PseudoHeaderName#PATH} header or {@code null} if there is no such header
*/
- AsciiString path();
+ ByteString path();
/**
* Gets the {@link PseudoHeaderName#STATUS} header or {@code null} if there is no such header
*/
- AsciiString status();
+ ByteString status();
}
diff --git a/codec-http2/src/main/java/io/netty/handler/codec/http2/Http2HeadersEncoder.java b/codec-http2/src/main/java/io/netty/handler/codec/http2/Http2HeadersEncoder.java
index ee8a2904ad..8f816aa679 100644
--- a/codec-http2/src/main/java/io/netty/handler/codec/http2/Http2HeadersEncoder.java
+++ b/codec-http2/src/main/java/io/netty/handler/codec/http2/Http2HeadersEncoder.java
@@ -16,7 +16,7 @@
package io.netty.handler.codec.http2;
import io.netty.buffer.ByteBuf;
-import io.netty.handler.codec.AsciiString;
+import io.netty.util.ByteString;
/**
* Encodes {@link Http2Headers} into HPACK-encoded headers blocks.
@@ -47,7 +47,7 @@ public interface Http2HeadersEncoder {
* sensitive.
* {@code false} otherwise.
*/
- boolean isSensitive(AsciiString name, AsciiString value);
+ boolean isSensitive(ByteString name, ByteString value);
}
/**
@@ -64,11 +64,11 @@ public interface Http2HeadersEncoder {
Configuration configuration();
/**
- * Always return {@code false} for {@link SensitivityDetector#isSensitive(AsciiString, AsciiString)}.
+ * Always return {@code false} for {@link SensitivityDetector#isSensitive(ByteString, ByteString)}.
*/
SensitivityDetector NEVER_SENSITIVE = new SensitivityDetector() {
@Override
- public boolean isSensitive(AsciiString name, AsciiString value) {
+ public boolean isSensitive(ByteString name, ByteString value) {
return false;
}
};
diff --git a/codec-http2/src/main/java/io/netty/handler/codec/http2/Http2ServerUpgradeCodec.java b/codec-http2/src/main/java/io/netty/handler/codec/http2/Http2ServerUpgradeCodec.java
index 4ef3138af4..f7d67b7073 100644
--- a/codec-http2/src/main/java/io/netty/handler/codec/http2/Http2ServerUpgradeCodec.java
+++ b/codec-http2/src/main/java/io/netty/handler/codec/http2/Http2ServerUpgradeCodec.java
@@ -23,15 +23,17 @@ import static io.netty.handler.codec.http2.Http2CodecUtil.writeFrameHeader;
import static io.netty.handler.codec.http2.Http2FrameTypes.SETTINGS;
import static io.netty.util.internal.ObjectUtil.checkNotNull;
import io.netty.buffer.ByteBuf;
+import io.netty.buffer.ByteBufUtil;
import io.netty.buffer.Unpooled;
import io.netty.channel.ChannelHandlerContext;
-import io.netty.handler.codec.AsciiString;
import io.netty.handler.codec.base64.Base64;
import io.netty.handler.codec.http.FullHttpRequest;
import io.netty.handler.codec.http.FullHttpResponse;
import io.netty.handler.codec.http.HttpServerUpgradeHandler;
+import io.netty.util.ByteString;
import io.netty.util.CharsetUtil;
+import java.nio.CharBuffer;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
@@ -104,8 +106,7 @@ public class Http2ServerUpgradeCodec implements HttpServerUpgradeHandler.Upgrade
@Override
public void upgradeTo(final ChannelHandlerContext ctx, FullHttpRequest upgradeRequest,
FullHttpResponse upgradeResponse) {
- // Add the HTTP/2 connection handler to the pipeline immediately following the current
- // handler.
+ // Add the HTTP/2 connection handler to the pipeline immediately following the current handler.
ctx.pipeline().addAfter(ctx.name(), handlerName, connectionHandler);
}
@@ -114,7 +115,7 @@ public class Http2ServerUpgradeCodec implements HttpServerUpgradeHandler.Upgrade
*/
private Http2Settings decodeSettingsHeader(ChannelHandlerContext ctx, CharSequence settingsHeader)
throws Http2Exception {
- ByteBuf header = Unpooled.wrappedBuffer(AsciiString.getBytes(settingsHeader, CharsetUtil.UTF_8));
+ ByteBuf header = ByteBufUtil.encodeString(ctx.alloc(), CharBuffer.wrap(settingsHeader), CharsetUtil.UTF_8);
try {
// Decode the SETTINGS payload.
ByteBuf payload = Base64.decode(header, URL_SAFE);
diff --git a/codec-http2/src/main/java/io/netty/handler/codec/http2/HttpUtil.java b/codec-http2/src/main/java/io/netty/handler/codec/http2/HttpUtil.java
index c535484684..c4c5d4b70b 100644
--- a/codec-http2/src/main/java/io/netty/handler/codec/http2/HttpUtil.java
+++ b/codec-http2/src/main/java/io/netty/handler/codec/http2/HttpUtil.java
@@ -18,7 +18,6 @@ import static io.netty.handler.codec.http2.Http2Error.PROTOCOL_ERROR;
import static io.netty.handler.codec.http2.Http2Exception.connectionError;
import static io.netty.handler.codec.http2.Http2Exception.streamError;
import static io.netty.util.internal.ObjectUtil.checkNotNull;
-import io.netty.handler.codec.AsciiString;
import io.netty.handler.codec.BinaryHeaders;
import io.netty.handler.codec.TextHeaders.EntryVisitor;
import io.netty.handler.codec.http.DefaultFullHttpRequest;
@@ -35,6 +34,8 @@ import io.netty.handler.codec.http.HttpRequest;
import io.netty.handler.codec.http.HttpResponse;
import io.netty.handler.codec.http.HttpResponseStatus;
import io.netty.handler.codec.http.HttpVersion;
+import io.netty.util.AsciiString;
+import io.netty.util.ByteString;
import java.net.URI;
import java.util.HashMap;
@@ -168,7 +169,7 @@ public final class HttpUtil {
* @return The HTTP/1.x status
* @throws Http2Exception If there is a problem translating from HTTP/2 to HTTP/1.x
*/
- public static HttpResponseStatus parseStatus(AsciiString status) throws Http2Exception {
+ public static HttpResponseStatus parseStatus(ByteString status) throws Http2Exception {
HttpResponseStatus result;
try {
result = HttpResponseStatus.parseLine(status);
@@ -220,11 +221,10 @@ public final class HttpUtil {
*/
public static FullHttpRequest toHttpRequest(int streamId, Http2Headers http2Headers, boolean validateHttpHeaders)
throws Http2Exception {
- // HTTP/2 does not define a way to carry the version identifier that is
- // included in the HTTP/1.1 request line.
- final AsciiString method = checkNotNull(http2Headers.method(),
+ // HTTP/2 does not define a way to carry the version identifier that is included in the HTTP/1.1 request line.
+ final ByteString method = checkNotNull(http2Headers.method(),
"method header cannot be null in conversion to HTTP/1.x");
- final AsciiString path = checkNotNull(http2Headers.path(),
+ final ByteString path = checkNotNull(http2Headers.path(),
"path header cannot be null in conversion to HTTP/1.x");
FullHttpRequest msg = new DefaultFullHttpRequest(HttpVersion.HTTP_1_1, HttpMethod.valueOf(method
.toString()), path.toString(), validateHttpHeaders);
@@ -330,10 +330,10 @@ public final class HttpUtil {
/**
* Translations from HTTP/2 header name to the HTTP/1.x equivalent.
*/
- private static final Map
- REQUEST_HEADER_TRANSLATIONS = new HashMap();
- private static final Map
- RESPONSE_HEADER_TRANSLATIONS = new HashMap();
+ private static final Map
+ REQUEST_HEADER_TRANSLATIONS = new HashMap();
+ private static final Map
+ RESPONSE_HEADER_TRANSLATIONS = new HashMap();
static {
RESPONSE_HEADER_TRANSLATIONS.put(Http2Headers.PseudoHeaderName.AUTHORITY.value(),
ExtensionHeaderNames.AUTHORITY.text());
@@ -346,7 +346,7 @@ public final class HttpUtil {
private final int streamId;
private final HttpHeaders output;
- private final Map translations;
+ private final Map translations;
/**
* Create a new instance
@@ -362,10 +362,10 @@ public final class HttpUtil {
}
@Override
- public boolean visit(Entry entry) throws Http2Exception {
- final AsciiString name = entry.getKey();
- final AsciiString value = entry.getValue();
- AsciiString translatedName = translations.get(name);
+ public boolean visit(Entry entry) throws Http2Exception {
+ final ByteString name = entry.getKey();
+ final ByteString value = entry.getValue();
+ ByteString translatedName = translations.get(name);
if (translatedName != null || !Http2Headers.PseudoHeaderName.isPseudoHeader(name)) {
if (translatedName == null) {
translatedName = name;
@@ -373,11 +373,11 @@ public final class HttpUtil {
// http://tools.ietf.org/html/draft-ietf-httpbis-http2-16#section-8.1.2.3
// All headers that start with ':' are only valid in HTTP/2 context
- if (translatedName.isEmpty() || translatedName.charAt(0) == ':') {
+ if (translatedName.isEmpty() || translatedName.byteAt(0) == ':') {
throw streamError(streamId, PROTOCOL_ERROR,
"Invalid HTTP/2 header '%s' encountered in translation to HTTP/1.x", translatedName);
} else {
- output.add(translatedName, value);
+ output.add(translatedName.toString(), value);
}
}
return true;
diff --git a/codec-http2/src/main/java/io/netty/handler/codec/http2/InboundHttp2ToHttpPriorityAdapter.java b/codec-http2/src/main/java/io/netty/handler/codec/http2/InboundHttp2ToHttpPriorityAdapter.java
index 6b6ed9570a..d4e4a0a1d3 100644
--- a/codec-http2/src/main/java/io/netty/handler/codec/http2/InboundHttp2ToHttpPriorityAdapter.java
+++ b/codec-http2/src/main/java/io/netty/handler/codec/http2/InboundHttp2ToHttpPriorityAdapter.java
@@ -16,14 +16,15 @@ package io.netty.handler.codec.http2;
import static io.netty.handler.codec.http2.Http2Error.PROTOCOL_ERROR;
import static io.netty.handler.codec.http2.Http2Exception.connectionError;
+
import java.util.Map.Entry;
import io.netty.channel.ChannelHandlerContext;
-import io.netty.handler.codec.AsciiString;
import io.netty.handler.codec.TextHeaders.EntryVisitor;
import io.netty.handler.codec.http.DefaultHttpHeaders;
import io.netty.handler.codec.http.FullHttpMessage;
import io.netty.handler.codec.http.HttpHeaders;
+import io.netty.util.AsciiString;
import io.netty.util.collection.IntObjectHashMap;
import io.netty.util.collection.IntObjectMap;
import io.netty.util.internal.PlatformDependent;
diff --git a/codec-http2/src/test/java/io/netty/handler/codec/http2/DataCompressionHttp2Test.java b/codec-http2/src/test/java/io/netty/handler/codec/http2/DataCompressionHttp2Test.java
index 8e28fc2e58..43b917e8c3 100644
--- a/codec-http2/src/test/java/io/netty/handler/codec/http2/DataCompressionHttp2Test.java
+++ b/codec-http2/src/test/java/io/netty/handler/codec/http2/DataCompressionHttp2Test.java
@@ -40,12 +40,12 @@ import io.netty.channel.ChannelPromise;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.nio.NioServerSocketChannel;
import io.netty.channel.socket.nio.NioSocketChannel;
-import io.netty.handler.codec.AsciiString;
import io.netty.handler.codec.http.HttpHeaderNames;
import io.netty.handler.codec.http.HttpHeaderValues;
import io.netty.handler.codec.http2.Http2TestUtil.FrameAdapter;
import io.netty.handler.codec.http2.Http2TestUtil.FrameCountDown;
import io.netty.handler.codec.http2.Http2TestUtil.Http2Runnable;
+import io.netty.util.AsciiString;
import io.netty.util.CharsetUtil;
import io.netty.util.NetUtil;
import io.netty.util.concurrent.Future;
diff --git a/codec-http2/src/test/java/io/netty/handler/codec/http2/DefaultHttp2HeadersTest.java b/codec-http2/src/test/java/io/netty/handler/codec/http2/DefaultHttp2HeadersTest.java
index 6e00b84297..52dd37bb8f 100644
--- a/codec-http2/src/test/java/io/netty/handler/codec/http2/DefaultHttp2HeadersTest.java
+++ b/codec-http2/src/test/java/io/netty/handler/codec/http2/DefaultHttp2HeadersTest.java
@@ -15,30 +15,41 @@
*/
package io.netty.handler.codec.http2;
-import io.netty.handler.codec.AsciiString;
-import org.junit.Test;
-
+import static org.junit.Assert.assertArrayEquals;
import static org.junit.Assert.assertEquals;
+import io.netty.util.AsciiString;
+import io.netty.util.ByteString;
+import io.netty.util.CharsetUtil;
+
+import org.junit.Test;
public class DefaultHttp2HeadersTest {
- private static final AsciiString NAME = new AsciiString("Test");
- private static final AsciiString VALUE = new AsciiString("some value");
+ private static final byte[] NAME_BYTES = { 'T', 'E', 's', 'T' };
+ private static final byte[] NAME_BYTES_LOWERCASE = { 't', 'e', 's', 't' };
+ private static final ByteString NAME_BYTESTRING = new ByteString(NAME_BYTES);
+ private static final AsciiString NAME_ASCIISTRING = new AsciiString("Test");
+ private static final ByteString VALUE = new ByteString("some value", CharsetUtil.UTF_8);
@Test
public void defaultLowercase() {
- Http2Headers headers = new DefaultHttp2Headers().set(NAME, VALUE);
- assertEquals(first(headers), NAME.toLowerCase());
+ Http2Headers headers = new DefaultHttp2Headers().set(NAME_BYTESTRING, VALUE);
+ assertArrayEquals(NAME_BYTES_LOWERCASE, first(headers).toByteArray());
+ }
+
+ @Test
+ public void defaultLowercaseAsciiString() {
+ Http2Headers headers = new DefaultHttp2Headers().set(NAME_ASCIISTRING, VALUE);
+ assertEquals(NAME_ASCIISTRING.toLowerCase(), first(headers));
}
@Test
public void caseInsensitive() {
- Http2Headers headers = new DefaultHttp2Headers(false).set(NAME, VALUE);
- assertEquals(first(headers), NAME);
+ Http2Headers headers = new DefaultHttp2Headers(false).set(NAME_BYTESTRING, VALUE);
+ assertArrayEquals(NAME_BYTES, first(headers).toByteArray());
}
- private static AsciiString first(Http2Headers headers) {
+ private static ByteString first(Http2Headers headers) {
return headers.names().iterator().next();
}
-
}
diff --git a/codec-http2/src/test/java/io/netty/handler/codec/http2/Http2TestUtil.java b/codec-http2/src/test/java/io/netty/handler/codec/http2/Http2TestUtil.java
index 5555cabf4a..7957643f77 100644
--- a/codec-http2/src/test/java/io/netty/handler/codec/http2/Http2TestUtil.java
+++ b/codec-http2/src/test/java/io/netty/handler/codec/http2/Http2TestUtil.java
@@ -17,8 +17,9 @@ package io.netty.handler.codec.http2;
import io.netty.buffer.ByteBuf;
import io.netty.channel.Channel;
import io.netty.channel.ChannelHandlerContext;
-import io.netty.handler.codec.AsciiString;
import io.netty.handler.codec.ByteToMessageDecoder;
+import io.netty.util.AsciiString;
+import io.netty.util.ByteString;
import java.util.List;
import java.util.Random;
@@ -61,8 +62,8 @@ final class Http2TestUtil {
/**
* Converts a byte array into an {@link AsciiString}.
*/
- public static AsciiString as(byte[] value) {
- return new AsciiString(value);
+ public static ByteString as(byte[] value) {
+ return new ByteString(value);
}
/**
@@ -77,7 +78,7 @@ final class Http2TestUtil {
/**
* Returns an {@link AsciiString} that wraps a randomly-filled byte array.
*/
- public static AsciiString randomString() {
+ public static ByteString randomString() {
return as(randomBytes());
}
diff --git a/codec-http2/src/test/java/io/netty/handler/codec/http2/InboundHttp2ToHttpAdapterTest.java b/codec-http2/src/test/java/io/netty/handler/codec/http2/InboundHttp2ToHttpAdapterTest.java
index ded34c9aa9..807721da6f 100644
--- a/codec-http2/src/test/java/io/netty/handler/codec/http2/InboundHttp2ToHttpAdapterTest.java
+++ b/codec-http2/src/test/java/io/netty/handler/codec/http2/InboundHttp2ToHttpAdapterTest.java
@@ -40,7 +40,6 @@ import io.netty.channel.SimpleChannelInboundHandler;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.nio.NioServerSocketChannel;
import io.netty.channel.socket.nio.NioSocketChannel;
-import io.netty.handler.codec.AsciiString;
import io.netty.handler.codec.http.DefaultFullHttpRequest;
import io.netty.handler.codec.http.DefaultFullHttpResponse;
import io.netty.handler.codec.http.FullHttpMessage;
@@ -54,6 +53,7 @@ import io.netty.handler.codec.http.HttpResponseStatus;
import io.netty.handler.codec.http.HttpVersion;
import io.netty.handler.codec.http2.Http2TestUtil.FrameAdapter;
import io.netty.handler.codec.http2.Http2TestUtil.Http2Runnable;
+import io.netty.util.AsciiString;
import io.netty.util.CharsetUtil;
import io.netty.util.NetUtil;
import io.netty.util.concurrent.Future;
diff --git a/codec-stomp/src/main/java/io/netty/handler/codec/stomp/StompHeaders.java b/codec-stomp/src/main/java/io/netty/handler/codec/stomp/StompHeaders.java
index 5bc5aeccdc..89c93db414 100644
--- a/codec-stomp/src/main/java/io/netty/handler/codec/stomp/StompHeaders.java
+++ b/codec-stomp/src/main/java/io/netty/handler/codec/stomp/StompHeaders.java
@@ -15,8 +15,8 @@
*/
package io.netty.handler.codec.stomp;
-import io.netty.handler.codec.AsciiString;
import io.netty.handler.codec.TextHeaders;
+import io.netty.util.AsciiString;
/**
* The multimap data structure for the STOMP header names and values. It also provides the constants for the standard
diff --git a/codec/src/main/java/io/netty/handler/codec/AsciiHeadersEncoder.java b/codec/src/main/java/io/netty/handler/codec/AsciiHeadersEncoder.java
index 805603ffb3..0531809e81 100644
--- a/codec/src/main/java/io/netty/handler/codec/AsciiHeadersEncoder.java
+++ b/codec/src/main/java/io/netty/handler/codec/AsciiHeadersEncoder.java
@@ -20,7 +20,9 @@ package io.netty.handler.codec;
import java.util.Map.Entry;
import io.netty.buffer.ByteBuf;
+import io.netty.buffer.ByteBufUtil;
import io.netty.handler.codec.TextHeaders.EntryVisitor;
+import io.netty.util.AsciiString;
public final class AsciiHeadersEncoder implements EntryVisitor {
@@ -129,7 +131,7 @@ public final class AsciiHeadersEncoder implements EntryVisitor {
}
private static void writeAsciiString(ByteBuf buf, int offset, AsciiString value, int valueLen) {
- value.copy(0, buf, offset, valueLen);
+ ByteBufUtil.copy(value, 0, buf, offset, valueLen);
}
private static void writeCharSequence(ByteBuf buf, int offset, CharSequence value, int valueLen) {
diff --git a/codec/src/main/java/io/netty/handler/codec/BinaryHeaders.java b/codec/src/main/java/io/netty/handler/codec/BinaryHeaders.java
index a998decc0a..b220320da3 100644
--- a/codec/src/main/java/io/netty/handler/codec/BinaryHeaders.java
+++ b/codec/src/main/java/io/netty/handler/codec/BinaryHeaders.java
@@ -16,68 +16,70 @@
package io.netty.handler.codec;
+import io.netty.util.ByteString;
+
/**
- * A typical {@code AsciiString} multimap used by protocols that use binary headers (such as HTTP/2) for the
- * representation of arbitrary key-value data. {@link AsciiString} is just a wrapper around a byte array but provides
+ * A typical {@code ByteString} multimap used by protocols that use binary headers (such as HTTP/2) for the
+ * representation of arbitrary key-value data. {@link ByteString} is just a wrapper around a byte array but provides
* some additional utility when handling text data.
*/
-public interface BinaryHeaders extends Headers {
+public interface BinaryHeaders extends Headers {
/**
- * A visitor that helps reduce GC pressure while iterating over a collection of {@link Headers}.
+ * Provides an abstraction to iterate over elements maintained in the {@link Headers} collection.
*/
- interface EntryVisitor extends Headers.EntryVisitor {
+ interface EntryVisitor extends Headers.EntryVisitor {
}
/**
- * A visitor that helps reduce GC pressure while iterating over a collection of {@link Headers}.
+ * Provides an abstraction to iterate over elements maintained in the {@link Headers} collection.
*/
- interface NameVisitor extends Headers.NameVisitor {
+ interface NameVisitor extends Headers.NameVisitor {
}
@Override
- BinaryHeaders add(AsciiString name, AsciiString value);
+ BinaryHeaders add(ByteString name, ByteString value);
@Override
- BinaryHeaders add(AsciiString name, Iterable extends AsciiString> values);
+ BinaryHeaders add(ByteString name, Iterable extends ByteString> values);
@Override
- BinaryHeaders add(AsciiString name, AsciiString... values);
+ BinaryHeaders add(ByteString name, ByteString... values);
@Override
- BinaryHeaders addObject(AsciiString name, Object value);
+ BinaryHeaders addObject(ByteString name, Object value);
@Override
- BinaryHeaders addObject(AsciiString name, Iterable> values);
+ BinaryHeaders addObject(ByteString name, Iterable> values);
@Override
- BinaryHeaders addObject(AsciiString name, Object... values);
+ BinaryHeaders addObject(ByteString name, Object... values);
@Override
- BinaryHeaders addBoolean(AsciiString name, boolean value);
+ BinaryHeaders addBoolean(ByteString name, boolean value);
@Override
- BinaryHeaders addByte(AsciiString name, byte value);
+ BinaryHeaders addByte(ByteString name, byte value);
@Override
- BinaryHeaders addChar(AsciiString name, char value);
+ BinaryHeaders addChar(ByteString name, char value);
@Override
- BinaryHeaders addShort(AsciiString name, short value);
+ BinaryHeaders addShort(ByteString name, short value);
@Override
- BinaryHeaders addInt(AsciiString name, int value);
+ BinaryHeaders addInt(ByteString name, int value);
@Override
- BinaryHeaders addLong(AsciiString name, long value);
+ BinaryHeaders addLong(ByteString name, long value);
@Override
- BinaryHeaders addFloat(AsciiString name, float value);
+ BinaryHeaders addFloat(ByteString name, float value);
@Override
- BinaryHeaders addDouble(AsciiString name, double value);
+ BinaryHeaders addDouble(ByteString name, double value);
@Override
- BinaryHeaders addTimeMillis(AsciiString name, long value);
+ BinaryHeaders addTimeMillis(ByteString name, long value);
/**
* See {@link Headers#add(Headers)}
@@ -85,49 +87,49 @@ public interface BinaryHeaders extends Headers {
BinaryHeaders add(BinaryHeaders headers);
@Override
- BinaryHeaders set(AsciiString name, AsciiString value);
+ BinaryHeaders set(ByteString name, ByteString value);
@Override
- BinaryHeaders set(AsciiString name, Iterable extends AsciiString> values);
+ BinaryHeaders set(ByteString name, Iterable extends ByteString> values);
@Override
- BinaryHeaders set(AsciiString name, AsciiString... values);
+ BinaryHeaders set(ByteString name, ByteString... values);
@Override
- BinaryHeaders setObject(AsciiString name, Object value);
+ BinaryHeaders setObject(ByteString name, Object value);
@Override
- BinaryHeaders setObject(AsciiString name, Iterable> values);
+ BinaryHeaders setObject(ByteString name, Iterable> values);
@Override
- BinaryHeaders setObject(AsciiString name, Object... values);
+ BinaryHeaders setObject(ByteString name, Object... values);
@Override
- BinaryHeaders setBoolean(AsciiString name, boolean value);
+ BinaryHeaders setBoolean(ByteString name, boolean value);
@Override
- BinaryHeaders setByte(AsciiString name, byte value);
+ BinaryHeaders setByte(ByteString name, byte value);
@Override
- BinaryHeaders setChar(AsciiString name, char value);
+ BinaryHeaders setChar(ByteString name, char value);
@Override
- BinaryHeaders setShort(AsciiString name, short value);
+ BinaryHeaders setShort(ByteString name, short value);
@Override
- BinaryHeaders setInt(AsciiString name, int value);
+ BinaryHeaders setInt(ByteString name, int value);
@Override
- BinaryHeaders setLong(AsciiString name, long value);
+ BinaryHeaders setLong(ByteString name, long value);
@Override
- BinaryHeaders setFloat(AsciiString name, float value);
+ BinaryHeaders setFloat(ByteString name, float value);
@Override
- BinaryHeaders setDouble(AsciiString name, double value);
+ BinaryHeaders setDouble(ByteString name, double value);
@Override
- BinaryHeaders setTimeMillis(AsciiString name, long value);
+ BinaryHeaders setTimeMillis(ByteString name, long value);
/**
* See {@link Headers#set(Headers)}
diff --git a/codec/src/main/java/io/netty/handler/codec/DefaultBinaryHeaders.java b/codec/src/main/java/io/netty/handler/codec/DefaultBinaryHeaders.java
index 3c484603ed..ae1b32b507 100644
--- a/codec/src/main/java/io/netty/handler/codec/DefaultBinaryHeaders.java
+++ b/codec/src/main/java/io/netty/handler/codec/DefaultBinaryHeaders.java
@@ -14,80 +14,74 @@
*/
package io.netty.handler.codec;
+import io.netty.util.ByteString;
+import io.netty.util.CharsetUtil;
import io.netty.util.internal.PlatformDependent;
+import java.nio.charset.Charset;
import java.text.ParseException;
-import static io.netty.handler.codec.AsciiString.*;
-
-public class DefaultBinaryHeaders extends DefaultHeaders implements BinaryHeaders {
- private static final HashCodeGenerator ASCII_HASH_CODE_GENERATOR =
- new HashCodeGenerator() {
+public class DefaultBinaryHeaders extends DefaultHeaders implements BinaryHeaders {
+ private static final ValueConverter OBJECT_TO_BYTE = new ValueConverter() {
+ private final Charset DEFAULT_CHARSET = CharsetUtil.UTF_8;
@Override
- public int generateHashCode(AsciiString name) {
- return AsciiString.caseInsensitiveHashCode(name);
- }
- };
-
- private static final ValueConverter OBJECT_TO_ASCII = new ValueConverter() {
- @Override
- public AsciiString convertObject(Object value) {
- if (value instanceof AsciiString) {
- return (AsciiString) value;
+ public ByteString convertObject(Object value) {
+ if (value instanceof ByteString) {
+ return (ByteString) value;
}
if (value instanceof CharSequence) {
- return new AsciiString((CharSequence) value);
+ return new ByteString((CharSequence) value, DEFAULT_CHARSET);
}
- return new AsciiString(value.toString());
+ return new ByteString(value.toString(), DEFAULT_CHARSET);
}
@Override
- public AsciiString convertInt(int value) {
- return new AsciiString(String.valueOf(value));
+ public ByteString convertInt(int value) {
+ return new ByteString(String.valueOf(value), DEFAULT_CHARSET);
}
@Override
- public AsciiString convertLong(long value) {
- return new AsciiString(String.valueOf(value));
+ public ByteString convertLong(long value) {
+ return new ByteString(String.valueOf(value), DEFAULT_CHARSET);
}
@Override
- public AsciiString convertDouble(double value) {
- return new AsciiString(String.valueOf(value));
+ public ByteString convertDouble(double value) {
+ return new ByteString(String.valueOf(value), DEFAULT_CHARSET);
}
@Override
- public AsciiString convertChar(char value) {
- return new AsciiString(String.valueOf(value));
+ public ByteString convertChar(char value) {
+ return new ByteString(String.valueOf(value), DEFAULT_CHARSET);
}
@Override
- public AsciiString convertBoolean(boolean value) {
- return new AsciiString(String.valueOf(value));
+ public ByteString convertBoolean(boolean value) {
+ return new ByteString(String.valueOf(value), DEFAULT_CHARSET);
}
@Override
- public AsciiString convertFloat(float value) {
- return new AsciiString(String.valueOf(value));
+ public ByteString convertFloat(float value) {
+ return new ByteString(String.valueOf(value), DEFAULT_CHARSET);
}
@Override
- public int convertToInt(AsciiString value) {
- return value.parseInt();
+ public int convertToInt(ByteString value) {
+ return value.parseAsciiInt();
}
@Override
- public long convertToLong(AsciiString value) {
- return value.parseLong();
+ public long convertToLong(ByteString value) {
+ return value.parseAsciiLong();
}
@Override
- public AsciiString convertTimeMillis(long value) {
- return new AsciiString(String.valueOf(value));
+ public ByteString convertTimeMillis(long value) {
+ return new ByteString(String.valueOf(value), DEFAULT_CHARSET);
}
@Override
- public long convertToTimeMillis(AsciiString value) {
+ public long convertToTimeMillis(ByteString value) {
try {
return HeaderDateFormat.get().parse(value.toString());
} catch (ParseException e) {
@@ -97,155 +91,145 @@ public class DefaultBinaryHeaders extends DefaultHeaders implements
}
@Override
- public double convertToDouble(AsciiString value) {
- return value.parseDouble();
+ public double convertToDouble(ByteString value) {
+ return value.parseAsciiDouble();
}
@Override
- public char convertToChar(AsciiString value) {
- return value.charAt(0);
+ public char convertToChar(ByteString value) {
+ return value.parseChar();
}
@Override
- public boolean convertToBoolean(AsciiString value) {
+ public boolean convertToBoolean(ByteString value) {
return value.byteAt(0) != 0;
}
@Override
- public float convertToFloat(AsciiString value) {
- return value.parseFloat();
+ public float convertToFloat(ByteString value) {
+ return value.parseAsciiFloat();
}
@Override
- public AsciiString convertShort(short value) {
- return new AsciiString(String.valueOf(value));
+ public ByteString convertShort(short value) {
+ return new ByteString(String.valueOf(value), DEFAULT_CHARSET);
}
@Override
- public short convertToShort(AsciiString value) {
- return value.parseShort();
+ public short convertToShort(ByteString value) {
+ return value.parseAsciiShort();
}
@Override
- public AsciiString convertByte(byte value) {
- return new AsciiString(String.valueOf(value));
+ public ByteString convertByte(byte value) {
+ return new ByteString(String.valueOf(value), DEFAULT_CHARSET);
}
@Override
- public byte convertToByte(AsciiString value) {
+ public byte convertToByte(ByteString value) {
return value.byteAt(0);
}
};
- private static final NameConverter ASCII_TO_LOWER_CONVERTER = new NameConverter() {
- @Override
- public AsciiString convertName(AsciiString name) {
- return name.toLowerCase();
- }
- };
-
- private static final NameConverter ASCII_IDENTITY_CONVERTER = new NameConverter() {
- @Override
- public AsciiString convertName(AsciiString name) {
- return name;
- }
- };
+ private static final HashCodeGenerator JAVA_HASH_CODE_GENERATOR =
+ new JavaHashCodeGenerator();
+ protected static final NameConverter IDENTITY_NAME_CONVERTER = new IdentityNameConverter();
public DefaultBinaryHeaders() {
- this(false);
+ this(IDENTITY_NAME_CONVERTER);
}
- public DefaultBinaryHeaders(boolean forceKeyToLower) {
- super(CASE_INSENSITIVE_ORDER, CASE_INSENSITIVE_ORDER, ASCII_HASH_CODE_GENERATOR, OBJECT_TO_ASCII,
- forceKeyToLower ? ASCII_TO_LOWER_CONVERTER : ASCII_IDENTITY_CONVERTER);
+ public DefaultBinaryHeaders(NameConverter nameConverter) {
+ super(ByteString.DEFAULT_COMPARATOR, ByteString.DEFAULT_COMPARATOR,
+ JAVA_HASH_CODE_GENERATOR, OBJECT_TO_BYTE, nameConverter);
}
@Override
- public BinaryHeaders add(AsciiString name, AsciiString value) {
+ public BinaryHeaders add(ByteString name, ByteString value) {
super.add(name, value);
return this;
}
@Override
- public BinaryHeaders add(AsciiString name, Iterable extends AsciiString> values) {
+ public BinaryHeaders add(ByteString name, Iterable extends ByteString> values) {
super.add(name, values);
return this;
}
@Override
- public BinaryHeaders add(AsciiString name, AsciiString... values) {
+ public BinaryHeaders add(ByteString name, ByteString... values) {
super.add(name, values);
return this;
}
@Override
- public BinaryHeaders addObject(AsciiString name, Object value) {
+ public BinaryHeaders addObject(ByteString name, Object value) {
super.addObject(name, value);
return this;
}
@Override
- public BinaryHeaders addObject(AsciiString name, Iterable> values) {
+ public BinaryHeaders addObject(ByteString name, Iterable> values) {
super.addObject(name, values);
return this;
}
@Override
- public BinaryHeaders addObject(AsciiString name, Object... values) {
+ public BinaryHeaders addObject(ByteString name, Object... values) {
super.addObject(name, values);
return this;
}
@Override
- public BinaryHeaders addBoolean(AsciiString name, boolean value) {
+ public BinaryHeaders addBoolean(ByteString name, boolean value) {
super.addBoolean(name, value);
return this;
}
@Override
- public BinaryHeaders addChar(AsciiString name, char value) {
+ public BinaryHeaders addChar(ByteString name, char value) {
super.addChar(name, value);
return this;
}
@Override
- public BinaryHeaders addByte(AsciiString name, byte value) {
+ public BinaryHeaders addByte(ByteString name, byte value) {
super.addByte(name, value);
return this;
}
@Override
- public BinaryHeaders addShort(AsciiString name, short value) {
+ public BinaryHeaders addShort(ByteString name, short value) {
super.addShort(name, value);
return this;
}
@Override
- public BinaryHeaders addInt(AsciiString name, int value) {
+ public BinaryHeaders addInt(ByteString name, int value) {
super.addInt(name, value);
return this;
}
@Override
- public BinaryHeaders addLong(AsciiString name, long value) {
+ public BinaryHeaders addLong(ByteString name, long value) {
super.addLong(name, value);
return this;
}
@Override
- public BinaryHeaders addFloat(AsciiString name, float value) {
+ public BinaryHeaders addFloat(ByteString name, float value) {
super.addFloat(name, value);
return this;
}
@Override
- public BinaryHeaders addDouble(AsciiString name, double value) {
+ public BinaryHeaders addDouble(ByteString name, double value) {
super.addDouble(name, value);
return this;
}
@Override
- public BinaryHeaders addTimeMillis(AsciiString name, long value) {
+ public BinaryHeaders addTimeMillis(ByteString name, long value) {
super.addTimeMillis(name, value);
return this;
}
@@ -257,91 +241,91 @@ public class DefaultBinaryHeaders extends DefaultHeaders implements
}
@Override
- public BinaryHeaders set(AsciiString name, AsciiString value) {
+ public BinaryHeaders set(ByteString name, ByteString value) {
super.set(name, value);
return this;
}
@Override
- public BinaryHeaders set(AsciiString name, Iterable extends AsciiString> values) {
+ public BinaryHeaders set(ByteString name, Iterable extends ByteString> values) {
super.set(name, values);
return this;
}
@Override
- public BinaryHeaders set(AsciiString name, AsciiString... values) {
+ public BinaryHeaders set(ByteString name, ByteString... values) {
super.set(name, values);
return this;
}
@Override
- public BinaryHeaders setObject(AsciiString name, Object value) {
+ public BinaryHeaders setObject(ByteString name, Object value) {
super.setObject(name, value);
return this;
}
@Override
- public BinaryHeaders setObject(AsciiString name, Iterable> values) {
+ public BinaryHeaders setObject(ByteString name, Iterable> values) {
super.setObject(name, values);
return this;
}
@Override
- public BinaryHeaders setObject(AsciiString name, Object... values) {
+ public BinaryHeaders setObject(ByteString name, Object... values) {
super.setObject(name, values);
return this;
}
@Override
- public BinaryHeaders setBoolean(AsciiString name, boolean value) {
+ public BinaryHeaders setBoolean(ByteString name, boolean value) {
super.setBoolean(name, value);
return this;
}
@Override
- public BinaryHeaders setChar(AsciiString name, char value) {
+ public BinaryHeaders setChar(ByteString name, char value) {
super.setChar(name, value);
return this;
}
@Override
- public BinaryHeaders setByte(AsciiString name, byte value) {
+ public BinaryHeaders setByte(ByteString name, byte value) {
super.setByte(name, value);
return this;
}
@Override
- public BinaryHeaders setShort(AsciiString name, short value) {
+ public BinaryHeaders setShort(ByteString name, short value) {
super.setShort(name, value);
return this;
}
@Override
- public BinaryHeaders setInt(AsciiString name, int value) {
+ public BinaryHeaders setInt(ByteString name, int value) {
super.setInt(name, value);
return this;
}
@Override
- public BinaryHeaders setLong(AsciiString name, long value) {
+ public BinaryHeaders setLong(ByteString name, long value) {
super.setLong(name, value);
return this;
}
@Override
- public BinaryHeaders setFloat(AsciiString name, float value) {
+ public BinaryHeaders setFloat(ByteString name, float value) {
super.setFloat(name, value);
return this;
}
@Override
- public BinaryHeaders setDouble(AsciiString name, double value) {
+ public BinaryHeaders setDouble(ByteString name, double value) {
super.setDouble(name, value);
return this;
}
@Override
- public BinaryHeaders setTimeMillis(AsciiString name, long value) {
+ public BinaryHeaders setTimeMillis(ByteString name, long value) {
super.setTimeMillis(name, value);
return this;
}
diff --git a/codec/src/main/java/io/netty/handler/codec/DefaultHeaders.java b/codec/src/main/java/io/netty/handler/codec/DefaultHeaders.java
index 60616415a8..37b7ba45a8 100644
--- a/codec/src/main/java/io/netty/handler/codec/DefaultHeaders.java
+++ b/codec/src/main/java/io/netty/handler/codec/DefaultHeaders.java
@@ -66,6 +66,16 @@ public class DefaultHeaders implements Headers {
T convertName(T name);
}
+ /**
+ * Uses the {@link #hashCode()} method to generate the hash code.
+ */
+ public static final class JavaHashCodeGenerator implements HashCodeGenerator {
+ @Override
+ public int generateHashCode(T name) {
+ return name.hashCode();
+ }
+ }
+
/**
* A name converted which does not covert but instead just returns this {@code name} unchanged
*/
diff --git a/codec/src/main/java/io/netty/handler/codec/DefaultTextHeaders.java b/codec/src/main/java/io/netty/handler/codec/DefaultTextHeaders.java
index 53efebcb3c..5f5f309059 100644
--- a/codec/src/main/java/io/netty/handler/codec/DefaultTextHeaders.java
+++ b/codec/src/main/java/io/netty/handler/codec/DefaultTextHeaders.java
@@ -16,6 +16,10 @@
package io.netty.handler.codec;
+import static io.netty.util.AsciiString.CHARSEQUENCE_CASE_INSENSITIVE_ORDER;
+import static io.netty.util.AsciiString.CHARSEQUENCE_CASE_SENSITIVE_ORDER;
+import static io.netty.util.internal.StringUtil.COMMA;
+import io.netty.util.AsciiString;
import io.netty.util.internal.PlatformDependent;
import io.netty.util.internal.StringUtil;
@@ -23,9 +27,6 @@ import java.text.ParseException;
import java.util.Comparator;
import java.util.Iterator;
-import static io.netty.handler.codec.AsciiString.*;
-import static io.netty.util.internal.StringUtil.COMMA;
-
public class DefaultTextHeaders extends DefaultConvertibleHeaders implements TextHeaders {
private static final HashCodeGenerator CHARSEQUECE_CASE_INSENSITIVE_HASH_CODE_GENERATOR =
new HashCodeGenerator() {
@@ -36,12 +37,7 @@ public class DefaultTextHeaders extends DefaultConvertibleHeaders CHARSEQUECE_CASE_SENSITIVE_HASH_CODE_GENERATOR =
- new HashCodeGenerator() {
- @Override
- public int generateHashCode(CharSequence name) {
- return name.hashCode();
- }
- };
+ new JavaHashCodeGenerator();
public static class DefaultTextValueTypeConverter implements ValueConverter {
@Override
diff --git a/codec/src/main/java/io/netty/handler/codec/EmptyBinaryHeaders.java b/codec/src/main/java/io/netty/handler/codec/EmptyBinaryHeaders.java
index b3e048e58f..98f248b2ac 100644
--- a/codec/src/main/java/io/netty/handler/codec/EmptyBinaryHeaders.java
+++ b/codec/src/main/java/io/netty/handler/codec/EmptyBinaryHeaders.java
@@ -16,96 +16,98 @@
package io.netty.handler.codec;
-public class EmptyBinaryHeaders extends EmptyHeaders implements BinaryHeaders {
+import io.netty.util.ByteString;
+
+public class EmptyBinaryHeaders extends EmptyHeaders implements BinaryHeaders {
protected EmptyBinaryHeaders() {
}
@Override
- public BinaryHeaders add(AsciiString name, AsciiString value) {
+ public BinaryHeaders add(ByteString name, ByteString value) {
super.add(name, value);
return this;
}
@Override
- public BinaryHeaders add(AsciiString name, Iterable extends AsciiString> values) {
+ public BinaryHeaders add(ByteString name, Iterable extends ByteString> values) {
super.add(name, values);
return this;
}
@Override
- public BinaryHeaders add(AsciiString name, AsciiString... values) {
+ public BinaryHeaders add(ByteString name, ByteString... values) {
super.add(name, values);
return this;
}
@Override
- public BinaryHeaders addObject(AsciiString name, Object value) {
+ public BinaryHeaders addObject(ByteString name, Object value) {
super.addObject(name, value);
return this;
}
@Override
- public BinaryHeaders addObject(AsciiString name, Iterable> values) {
+ public BinaryHeaders addObject(ByteString name, Iterable> values) {
super.addObject(name, values);
return this;
}
@Override
- public BinaryHeaders addObject(AsciiString name, Object... values) {
+ public BinaryHeaders addObject(ByteString name, Object... values) {
super.addObject(name, values);
return this;
}
@Override
- public BinaryHeaders addBoolean(AsciiString name, boolean value) {
+ public BinaryHeaders addBoolean(ByteString name, boolean value) {
super.addBoolean(name, value);
return this;
}
@Override
- public BinaryHeaders addChar(AsciiString name, char value) {
+ public BinaryHeaders addChar(ByteString name, char value) {
super.addChar(name, value);
return this;
}
@Override
- public BinaryHeaders addByte(AsciiString name, byte value) {
+ public BinaryHeaders addByte(ByteString name, byte value) {
super.addByte(name, value);
return this;
}
@Override
- public BinaryHeaders addShort(AsciiString name, short value) {
+ public BinaryHeaders addShort(ByteString name, short value) {
super.addShort(name, value);
return this;
}
@Override
- public BinaryHeaders addInt(AsciiString name, int value) {
+ public BinaryHeaders addInt(ByteString name, int value) {
super.addInt(name, value);
return this;
}
@Override
- public BinaryHeaders addLong(AsciiString name, long value) {
+ public BinaryHeaders addLong(ByteString name, long value) {
super.addLong(name, value);
return this;
}
@Override
- public BinaryHeaders addFloat(AsciiString name, float value) {
+ public BinaryHeaders addFloat(ByteString name, float value) {
super.addFloat(name, value);
return this;
}
@Override
- public BinaryHeaders addDouble(AsciiString name, double value) {
+ public BinaryHeaders addDouble(ByteString name, double value) {
super.addDouble(name, value);
return this;
}
@Override
- public BinaryHeaders addTimeMillis(AsciiString name, long value) {
+ public BinaryHeaders addTimeMillis(ByteString name, long value) {
super.addTimeMillis(name, value);
return this;
}
@@ -117,91 +119,91 @@ public class EmptyBinaryHeaders extends EmptyHeaders implements Bin
}
@Override
- public BinaryHeaders set(AsciiString name, AsciiString value) {
+ public BinaryHeaders set(ByteString name, ByteString value) {
super.set(name, value);
return this;
}
@Override
- public BinaryHeaders set(AsciiString name, Iterable extends AsciiString> values) {
+ public BinaryHeaders set(ByteString name, Iterable extends ByteString> values) {
super.set(name, values);
return this;
}
@Override
- public BinaryHeaders set(AsciiString name, AsciiString... values) {
+ public BinaryHeaders set(ByteString name, ByteString... values) {
super.set(name, values);
return this;
}
@Override
- public BinaryHeaders setObject(AsciiString name, Object value) {
+ public BinaryHeaders setObject(ByteString name, Object value) {
super.setObject(name, value);
return this;
}
@Override
- public BinaryHeaders setObject(AsciiString name, Iterable> values) {
+ public BinaryHeaders setObject(ByteString name, Iterable> values) {
super.setObject(name, values);
return this;
}
@Override
- public BinaryHeaders setObject(AsciiString name, Object... values) {
+ public BinaryHeaders setObject(ByteString name, Object... values) {
super.setObject(name, values);
return this;
}
@Override
- public BinaryHeaders setBoolean(AsciiString name, boolean value) {
+ public BinaryHeaders setBoolean(ByteString name, boolean value) {
super.setBoolean(name, value);
return this;
}
@Override
- public BinaryHeaders setChar(AsciiString name, char value) {
+ public BinaryHeaders setChar(ByteString name, char value) {
super.setChar(name, value);
return this;
}
@Override
- public BinaryHeaders setByte(AsciiString name, byte value) {
+ public BinaryHeaders setByte(ByteString name, byte value) {
super.setByte(name, value);
return this;
}
@Override
- public BinaryHeaders setShort(AsciiString name, short value) {
+ public BinaryHeaders setShort(ByteString name, short value) {
super.setShort(name, value);
return this;
}
@Override
- public BinaryHeaders setInt(AsciiString name, int value) {
+ public BinaryHeaders setInt(ByteString name, int value) {
super.setInt(name, value);
return this;
}
@Override
- public BinaryHeaders setLong(AsciiString name, long value) {
+ public BinaryHeaders setLong(ByteString name, long value) {
super.setLong(name, value);
return this;
}
@Override
- public BinaryHeaders setFloat(AsciiString name, float value) {
+ public BinaryHeaders setFloat(ByteString name, float value) {
super.setFloat(name, value);
return this;
}
@Override
- public BinaryHeaders setDouble(AsciiString name, double value) {
+ public BinaryHeaders setDouble(ByteString name, double value) {
super.setDouble(name, value);
return this;
}
@Override
- public BinaryHeaders setTimeMillis(AsciiString name, long value) {
+ public BinaryHeaders setTimeMillis(ByteString name, long value) {
super.setTimeMillis(name, value);
return this;
}
diff --git a/codec/src/main/java/io/netty/handler/codec/Headers.java b/codec/src/main/java/io/netty/handler/codec/Headers.java
index 643d1b13e8..9718c0c0e2 100644
--- a/codec/src/main/java/io/netty/handler/codec/Headers.java
+++ b/codec/src/main/java/io/netty/handler/codec/Headers.java
@@ -23,7 +23,7 @@ import java.util.Set;
public interface Headers extends Iterable> {
/**
- * A visitor that helps reduce GC pressure while iterating over a collection of {@link Headers}.
+ * Provides an abstraction to iterate over elements maintained in the {@link Headers} collection.
*/
interface EntryVisitor {
/**
@@ -36,7 +36,7 @@ public interface Headers extends Iterable> {
}
/**
- * A visitor that helps reduce GC pressure while iterating over a collection of {@link Headers}.
+ * Provides an abstraction to iterate over elements maintained in the {@link Headers} collection.
*/
interface NameVisitor {
/**
@@ -1095,16 +1095,14 @@ public interface Headers extends Iterable> {
Iterator> iterator();
/**
- * Provide a means of iterating over elements in this map with low GC
- *
+ * Provides an abstraction to iterate over elements maintained in the {@link Headers} collection.
* @param visitor The visitor which will visit each element in this map
* @return The last entry before iteration stopped or {@code null} if iteration went past the end
*/
Map.Entry forEachEntry(EntryVisitor visitor) throws Exception;
/**
- * Provide a means of iterating over elements in this map with low GC
- *
+ * Provides an abstraction to iterate over elements maintained in the {@link Headers} collection.
* @param visitor The visitor which will visit each element in this map
* @return The last key before iteration stopped or {@code null} if iteration went past the end
*/
diff --git a/codec/src/main/java/io/netty/handler/codec/ReplayingDecoderByteBuf.java b/codec/src/main/java/io/netty/handler/codec/ReplayingDecoderByteBuf.java
index 6d660dba03..24d06dc1ef 100644
--- a/codec/src/main/java/io/netty/handler/codec/ReplayingDecoderByteBuf.java
+++ b/codec/src/main/java/io/netty/handler/codec/ReplayingDecoderByteBuf.java
@@ -17,9 +17,9 @@ package io.netty.handler.codec;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.ByteBufAllocator;
-import io.netty.buffer.ByteBufProcessor;
import io.netty.buffer.SwappedByteBuf;
import io.netty.buffer.Unpooled;
+import io.netty.util.ByteProcessor;
import io.netty.util.Signal;
import io.netty.util.internal.StringUtil;
@@ -352,7 +352,7 @@ final class ReplayingDecoderByteBuf extends ByteBuf {
}
@Override
- public int forEachByte(ByteBufProcessor processor) {
+ public int forEachByte(ByteProcessor processor) {
int ret = buffer.forEachByte(processor);
if (ret < 0) {
throw REPLAY;
@@ -362,7 +362,7 @@ final class ReplayingDecoderByteBuf extends ByteBuf {
}
@Override
- public int forEachByte(int index, int length, ByteBufProcessor processor) {
+ public int forEachByte(int index, int length, ByteProcessor processor) {
final int writerIndex = buffer.writerIndex();
if (index >= writerIndex) {
throw REPLAY;
@@ -381,7 +381,7 @@ final class ReplayingDecoderByteBuf extends ByteBuf {
}
@Override
- public int forEachByteDesc(ByteBufProcessor processor) {
+ public int forEachByteDesc(ByteProcessor processor) {
if (terminated) {
return buffer.forEachByteDesc(processor);
} else {
@@ -391,7 +391,7 @@ final class ReplayingDecoderByteBuf extends ByteBuf {
}
@Override
- public int forEachByteDesc(int index, int length, ByteBufProcessor processor) {
+ public int forEachByteDesc(int index, int length, ByteProcessor processor) {
if (index + length > buffer.writerIndex()) {
throw REPLAY;
}
diff --git a/codec/src/test/java/io/netty/handler/codec/DefaultBinaryHeadersTest.java b/codec/src/test/java/io/netty/handler/codec/DefaultBinaryHeadersTest.java
index 6d477e07bc..c4bfb43b95 100644
--- a/codec/src/test/java/io/netty/handler/codec/DefaultBinaryHeadersTest.java
+++ b/codec/src/test/java/io/netty/handler/codec/DefaultBinaryHeadersTest.java
@@ -17,6 +17,8 @@ package io.netty.handler.codec;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
+import io.netty.util.AsciiString;
+import io.netty.util.ByteString;
import java.util.HashSet;
import java.util.Iterator;
@@ -40,11 +42,11 @@ public class DefaultBinaryHeadersTest {
byte[] key2 = randomBytes();
byte[] value2 = randomBytes();
- DefaultBinaryHeaders h1 = new DefaultBinaryHeaders(false);
+ DefaultBinaryHeaders h1 = new DefaultBinaryHeaders();
h1.set(as(key1), as(value1));
h1.set(as(key2), as(value2));
- DefaultBinaryHeaders h2 = new DefaultBinaryHeaders(false);
+ DefaultBinaryHeaders h2 = new DefaultBinaryHeaders();
h2.set(as(key1), as(value1));
h2.set(as(key2), as(value2));
@@ -63,13 +65,13 @@ public class DefaultBinaryHeadersTest {
byte[] v3 = randomBytes();
byte[] v4 = randomBytes();
- DefaultBinaryHeaders h1 = new DefaultBinaryHeaders(false);
+ DefaultBinaryHeaders h1 = new DefaultBinaryHeaders();
h1.set(as(k1), as(v1));
h1.set(as(k2), as(v2));
h1.add(as(k2), as(v3));
h1.add(as(k1), as(v4));
- DefaultBinaryHeaders h2 = new DefaultBinaryHeaders(false);
+ DefaultBinaryHeaders h2 = new DefaultBinaryHeaders();
h2.set(as(k1), as(v1));
h2.set(as(k2), as(v2));
h2.add(as(k1), as(v4));
@@ -90,13 +92,13 @@ public class DefaultBinaryHeadersTest {
byte[] v3 = randomBytes();
byte[] v4 = randomBytes();
- DefaultBinaryHeaders h1 = new DefaultBinaryHeaders(false);
+ DefaultBinaryHeaders h1 = new DefaultBinaryHeaders();
h1.set(as(k1), as(v1));
h1.set(as(k2), as(v2));
h1.add(as(k2), as(v3));
h1.add(as(k1), as(v4));
- DefaultBinaryHeaders h2 = new DefaultBinaryHeaders(false);
+ DefaultBinaryHeaders h2 = new DefaultBinaryHeaders();
h2.set(as(k1), as(v1));
h2.set(as(k2), as(v2));
h2.add(as(k1), as(v4));
@@ -116,18 +118,18 @@ public class DefaultBinaryHeadersTest {
byte[] v3 = randomBytes();
byte[] v4 = randomBytes();
- DefaultBinaryHeaders h1 = new DefaultBinaryHeaders(false);
+ DefaultBinaryHeaders h1 = new DefaultBinaryHeaders();
h1.set(as(k1), as(v1));
h1.set(as(k2), as(v2));
h1.add(as(k2), as(v3));
h1.add(as(k1), as(v4));
- DefaultBinaryHeaders h2 = new DefaultBinaryHeaders(false);
+ DefaultBinaryHeaders h2 = new DefaultBinaryHeaders();
h2.set(as(k1), as(v1));
h2.set(as(k2), as(v2));
h2.add(as(k1), as(v4));
- DefaultBinaryHeaders expected = new DefaultBinaryHeaders(false);
+ DefaultBinaryHeaders expected = new DefaultBinaryHeaders();
expected.set(as(k1), as(v1));
expected.set(as(k2), as(v2));
expected.add(as(k2), as(v3));
@@ -148,14 +150,14 @@ public class DefaultBinaryHeadersTest {
byte[] v2 = randomBytes();
byte[] v3 = randomBytes();
- DefaultBinaryHeaders h1 = new DefaultBinaryHeaders(false);
+ DefaultBinaryHeaders h1 = new DefaultBinaryHeaders();
h1.add(as(k1), as(v1));
h1.add(as(k1), as(v2));
assertEquals(2, h1.size());
h1.set(as(k1), as(v3));
assertEquals(1, h1.size());
- List list = h1.getAll(as(k1));
+ List list = h1.getAll(as(k1));
assertEquals(1, list.size());
assertEquals(as(v3), list.get(0));
}
@@ -251,14 +253,14 @@ public class DefaultBinaryHeadersTest {
h1.set(as("foo"), as("goo3"));
assertEquals(1, h1.size());
- List list = h1.getAll(as("foo"));
+ List list = h1.getAll(as("foo"));
assertEquals(1, list.size());
assertEquals(as("goo3"), list.get(0));
}
@Test(expected = NoSuchElementException.class)
public void iterateEmptyHeadersShouldThrow() {
- Iterator> iterator = new DefaultBinaryHeaders().iterator();
+ Iterator> iterator = new DefaultBinaryHeaders().iterator();
assertFalse(iterator.hasNext());
iterator.next();
}
@@ -281,7 +283,7 @@ public class DefaultBinaryHeadersTest {
}
// Now iterate through the headers, removing them from the original set.
- for (Map.Entry entry : h1) {
+ for (Map.Entry entry : h1) {
assertTrue(headers.remove(entry.getKey().toString() + ':' + entry.getValue().toString()));
}
@@ -296,7 +298,7 @@ public class DefaultBinaryHeadersTest {
h1.add(as("foo"), as("goo2"));
assertEquals(as("goo"), h1.getAndRemove(as("foo")));
assertEquals(0, h1.size());
- List values = h1.getAll(as("foo"));
+ List values = h1.getAll(as("foo"));
assertEquals(0, values.size());
}
diff --git a/codec/src/main/java/io/netty/handler/codec/AsciiString.java b/common/src/main/java/io/netty/util/AsciiString.java
similarity index 64%
rename from codec/src/main/java/io/netty/handler/codec/AsciiString.java
rename to common/src/main/java/io/netty/util/AsciiString.java
index 7568c5e8c8..2e3d3d6918 100644
--- a/codec/src/main/java/io/netty/handler/codec/AsciiString.java
+++ b/common/src/main/java/io/netty/util/AsciiString.java
@@ -13,11 +13,13 @@
* License for the specific language governing permissions and limitations
* under the License.
*/
-package io.netty.handler.codec;
+package io.netty.util;
-import io.netty.buffer.ByteBuf;
-import io.netty.buffer.Unpooled;
+import static io.netty.util.internal.ObjectUtil.checkNotNull;
+import static io.netty.util.internal.StringUtil.UPPER_CASE_TO_LOWER_CASE_ASCII_OFFSET;
+import io.netty.util.ByteProcessor.IndexOfProcessor;
import io.netty.util.internal.EmptyArrays;
+import io.netty.util.internal.PlatformDependent;
import java.nio.ByteBuffer;
import java.nio.charset.Charset;
@@ -32,11 +34,13 @@ import java.util.regex.PatternSyntaxException;
* A string which has been encoded into a character encoding whose character always takes a single byte, similarly to
* ASCII. It internally keeps its content in a byte array unlike {@link String}, which uses a character array, for
* reduced memory footprint and faster data transfer from/to byte-based data structures such as a byte array and
- * {@link ByteBuf}. It is often used in conjunction with {@link TextHeaders}.
+ * {@link ByteBuffer}. It is often used in conjunction with {@link TextHeaders}.
*/
-public final class AsciiString implements CharSequence, Comparable {
+public final class AsciiString extends ByteString implements CharSequence, Comparable {
+ private static final char MAX_CHAR_VALUE = 255;
public static final AsciiString EMPTY_STRING = new AsciiString("");
+
public static final Comparator CASE_INSENSITIVE_ORDER = new Comparator() {
@Override
public int compare(AsciiString o1, AsciiString o2) {
@@ -73,8 +77,8 @@ public final class AsciiString implements CharSequence, Comparable
if (v1 == v2) {
continue;
}
- int c1 = toLowerCase(v1) & 0xFF;
- int c2 = toLowerCase(v2) & 0xFF;
+ int c1 = toLowerCase(v1);
+ int c2 = toLowerCase(v2);
result = c1 - c2;
if (result != 0) {
return result;
@@ -83,7 +87,7 @@ public final class AsciiString implements CharSequence, Comparable
} else if (a1 != null) {
byte[] thisValue = a1.value;
for (int i = 0; i < minLength; i++) {
- int c1 = toLowerCase(thisValue[i]) & 0xFF;
+ int c1 = toLowerCase(thisValue[i]);
int c2 = toLowerCase(o2.charAt(i));
result = c1 - c2;
if (result != 0) {
@@ -94,7 +98,7 @@ public final class AsciiString implements CharSequence, Comparable
byte[] thatValue = a2.value;
for (int i = 0; i < minLength; i++) {
int c1 = toLowerCase(o1.charAt(i));
- int c2 = toLowerCase(thatValue[i]) & 0xFF;
+ int c2 = toLowerCase(thatValue[i]);
result = c1 - c2;
if (result != 0) {
return result;
@@ -188,7 +192,7 @@ public final class AsciiString implements CharSequence, Comparable
int hash = 0;
final int end = value.length();
for (int i = 0; i < end; i++) {
- hash = hash * 31 ^ value.charAt(i) & 31;
+ hash = hash * HASH_CODE_PRIME ^ value.charAt(i) & HASH_CODE_PRIME;
}
return hash;
@@ -245,27 +249,7 @@ public final class AsciiString implements CharSequence, Comparable
return a.equals(b);
}
- public static byte[] getBytes(CharSequence v, Charset charset) {
- if (v instanceof AsciiString) {
- return ((AsciiString) v).array();
- } else if (v instanceof String) {
- return ((String) v).getBytes(charset);
- } else if (v != null) {
- final ByteBuf buf = Unpooled.copiedBuffer(v, charset);
- try {
- if (buf.hasArray()) {
- return buf.array();
- } else {
- byte[] result = new byte[buf.readableBytes()];
- buf.readBytes(result);
- return result;
- }
- } finally {
- buf.release();
- }
- }
- return null;
- }
+ private String string;
/**
* Returns an {@link AsciiString} containing the given character sequence. If the given string is already a
@@ -275,259 +259,113 @@ public final class AsciiString implements CharSequence, Comparable
return string instanceof AsciiString ? (AsciiString) string : new AsciiString(string);
}
- private final byte[] value;
- private String string;
- private int hash;
-
public AsciiString(byte[] value) {
- this(value, true);
+ super(value);
}
public AsciiString(byte[] value, boolean copy) {
- checkNull(value);
- if (copy) {
- this.value = value.clone();
- } else {
- this.value = value;
- }
+ super(value, copy);
}
public AsciiString(byte[] value, int start, int length) {
- this(value, start, length, true);
+ super(value, start, length);
}
public AsciiString(byte[] value, int start, int length, boolean copy) {
- checkNull(value);
- if (start < 0 || start > value.length - length) {
- throw new IndexOutOfBoundsException("expected: " + "0 <= start(" + start + ") <= start + length(" + length
- + ") <= " + "value.length(" + value.length + ')');
- }
+ super(value, start, length, copy);
+ }
- if (copy || start != 0 || length != value.length) {
- this.value = Arrays.copyOfRange(value, start, start + length);
- } else {
- this.value = value;
- }
+ public AsciiString(ByteBuffer value) {
+ super(value);
+ }
+
+ public AsciiString(ByteBuffer value, int start, int length) {
+ super(value, start, length);
+ }
+
+ public AsciiString(ByteBuffer value, int start, int length, boolean copy) {
+ super(value, start, length, copy);
}
public AsciiString(char[] value) {
- this(checkNull(value), 0, value.length);
+ this(checkNotNull(value, "value"), 0, value.length);
}
public AsciiString(char[] value, int start, int length) {
- checkNull(value);
- if (start < 0 || start > value.length - length) {
+ super(length);
+ if (start < 0 || start > checkNotNull(value, "value").length - length) {
throw new IndexOutOfBoundsException("expected: " + "0 <= start(" + start + ") <= start + length(" + length
+ ") <= " + "value.length(" + value.length + ')');
}
- this.value = new byte[length];
for (int i = 0, j = start; i < length; i++, j++) {
this.value[i] = c2b(value[j]);
}
}
public AsciiString(CharSequence value) {
- this(checkNull(value), 0, value.length());
+ this(checkNotNull(value, "value"), 0, value.length());
}
public AsciiString(CharSequence value, int start, int length) {
- if (value == null) {
- throw new NullPointerException("value");
- }
-
- if (start < 0 || length < 0 || length > value.length() - start) {
+ super(length);
+ if (start < 0 || length < 0 || length > checkNotNull(value, "value").length() - start) {
throw new IndexOutOfBoundsException("expected: " + "0 <= start(" + start + ") <= start + length(" + length
+ ") <= " + "value.length(" + value.length() + ')');
}
- this.value = new byte[length];
for (int i = 0; i < length; i++) {
this.value[i] = c2b(value.charAt(start + i));
}
}
- public AsciiString(ByteBuffer value) {
- this(checkNull(value), value.position(), value.remaining());
- }
-
- public AsciiString(ByteBuffer value, int start, int length) {
- if (value == null) {
- throw new NullPointerException("value");
- }
-
- if (start < 0 || length > value.capacity() - start) {
- throw new IndexOutOfBoundsException("expected: " + "0 <= start(" + start + ") <= start + length(" + length
- + ") <= " + "value.capacity(" + value.capacity() + ')');
- }
-
- if (value.hasArray()) {
- int baseOffset = value.arrayOffset() + start;
- this.value = Arrays.copyOfRange(value.array(), baseOffset, baseOffset + length);
- } else {
- this.value = new byte[length];
- int oldPos = value.position();
- value.get(this.value, 0, this.value.length);
- value.position(oldPos);
- }
- }
-
- private static T checkNull(T value) {
- if (value == null) {
- throw new NullPointerException("value");
- }
- return value;
- }
-
- @Override
- public int length() {
- return value.length;
- }
-
@Override
public char charAt(int index) {
- return (char) (byteAt(index) & 0xFF);
- }
-
- public byte byteAt(int index) {
- return value[index];
- }
-
- public byte[] array() {
- return value;
- }
-
- public int arrayOffset() {
- return 0;
+ return b2c(byteAt(index));
}
private static byte c2b(char c) {
- if (c > 255) {
+ if (c > MAX_CHAR_VALUE) {
return '?';
}
return (byte) c;
}
+ private static char b2c(byte b) {
+ return (char) (b & 0xFF);
+ }
+
private static byte toLowerCase(byte b) {
if ('A' <= b && b <= 'Z') {
- return (byte) (b + 32);
+ return (byte) (b + UPPER_CASE_TO_LOWER_CASE_ASCII_OFFSET);
}
return b;
}
private static char toLowerCase(char c) {
if ('A' <= c && c <= 'Z') {
- return (char) (c + 32);
+ return (char) (c + UPPER_CASE_TO_LOWER_CASE_ASCII_OFFSET);
}
return c;
}
private static byte toUpperCase(byte b) {
if ('a' <= b && b <= 'z') {
- return (byte) (b - 32);
+ return (byte) (b - UPPER_CASE_TO_LOWER_CASE_ASCII_OFFSET);
}
return b;
}
- /**
- * Copies a range of characters into a new string.
- *
- * @param start the offset of the first character.
- * @return a new string containing the characters from start to the end of the string.
- * @throws IndexOutOfBoundsException if {@code start < 0} or {@code start > length()}.
- */
- public AsciiString subSequence(int start) {
- return subSequence(start, length());
- }
-
@Override
- public AsciiString subSequence(int start, int end) {
- if (start < 0 || start > end || end > length()) {
- throw new IndexOutOfBoundsException("expected: 0 <= start(" + start + ") <= end (" + end + ") <= length("
- + length() + ')');
- }
-
- final byte[] value = this.value;
- if (start == 0 && end == value.length) {
- return this;
- }
-
- if (end == start) {
- return EMPTY_STRING;
- }
-
- return new AsciiString(value, start, end - start, false);
- }
-
- @Override
- public int hashCode() {
- int hash = this.hash;
- final byte[] value = this.value;
- if (hash != 0 || value.length == 0) {
- return hash;
- }
-
- for (int i = 0; i < value.length; ++i) {
- hash = hash * 31 ^ value[i] & 31;
- }
-
- return this.hash = hash;
- }
-
- @Override
- public boolean equals(Object obj) {
- if (!(obj instanceof AsciiString)) {
- return false;
- }
-
- if (this == obj) {
- return true;
- }
-
- AsciiString that = (AsciiString) obj;
- int thisHash = hashCode();
- int thatHash = that.hashCode();
- if (thisHash != thatHash || length() != that.length()) {
- return false;
- }
-
- byte[] thisValue = value;
- byte[] thatValue = that.value;
- int end = thisValue.length;
- for (int i = 0, j = 0; i < end; i++, j++) {
- if (thisValue[i] != thatValue[j]) {
- return false;
+ public String toString(Charset charset, int start, int end) {
+ if (start == 0 && end == length()) {
+ if (string == null) {
+ string = super.toString(charset, start, end);
}
- }
-
- return true;
- }
-
- @Override
- @SuppressWarnings("deprecation")
- public String toString() {
- String string = this.string;
- if (string != null) {
return string;
}
- final byte[] value = this.value;
- return this.string = new String(value, 0, 0, value.length);
- }
-
- @SuppressWarnings("deprecation")
- public String toString(int start, int end) {
- final byte[] value = this.value;
- if (start == 0 && end == value.length) {
- return toString();
- }
-
- int length = end - start;
- if (length == 0) {
- return "";
- }
-
- return new String(value, 0, start, length);
+ return super.toString(charset, start, end);
}
/**
@@ -543,7 +381,6 @@ public final class AsciiString implements CharSequence, Comparable
* positive integer if this string is after the specified string.
* @throws NullPointerException if {@code string} is {@code null}.
*/
- @Override
public int compareTo(CharSequence string) {
if (this == string) {
return 0;
@@ -555,7 +392,7 @@ public final class AsciiString implements CharSequence, Comparable
int minLength = Math.min(length1, length2);
byte[] value = this.value;
for (int i = 0, j = 0; j < minLength; i++, j++) {
- result = (value[i] & 0xFF) - string.charAt(j);
+ result = b2c(value[i]) - string.charAt(j);
if (result != 0) {
return result;
}
@@ -648,7 +485,6 @@ public final class AsciiString implements CharSequence, Comparable
return false;
}
- final byte[] value = this.value;
final int thisLen = value.length;
final int thatLen = string.length();
if (thisLen != thatLen) {
@@ -656,7 +492,7 @@ public final class AsciiString implements CharSequence, Comparable
}
for (int i = 0; i < thisLen; i++) {
- char c1 = (char) (value[i] & 0xFF);
+ char c1 = b2c(value[i]);
char c2 = string.charAt(i);
if (c1 != c2 && toLowerCase(c1) != toLowerCase(c2)) {
return false;
@@ -665,24 +501,6 @@ public final class AsciiString implements CharSequence, Comparable
return true;
}
- /**
- * Converts this string to a byte array using the ASCII encoding.
- *
- * @return the byte array encoding of this string.
- */
- public byte[] toByteArray() {
- return toByteArray(0, length());
- }
-
- /**
- * Converts this string to a byte array using the ASCII encoding.
- *
- * @return the byte array encoding of this string.
- */
- public byte[] toByteArray(int start, int end) {
- return Arrays.copyOfRange(value, start, end);
- }
-
/**
* Copies the characters in this string to a character array.
*
@@ -703,85 +521,13 @@ public final class AsciiString implements CharSequence, Comparable
return EmptyArrays.EMPTY_CHARS;
}
- final byte[] value = this.value;
final char[] buffer = new char[length];
for (int i = 0, j = start; i < length; i++, j++) {
- buffer[i] = (char) (value[j] & 0xFF);
+ buffer[i] = b2c(value[j]);
}
return buffer;
}
- /**
- * Copies the content of this string to a {@link ByteBuf} using {@link ByteBuf#writeBytes(byte[], int, int)}.
- *
- * @param srcIdx the starting offset of characters to copy.
- * @param dst the destination byte array.
- * @param dstIdx the starting offset in the destination byte array.
- * @param length the number of characters to copy.
- */
- public void copy(int srcIdx, ByteBuf dst, int dstIdx, int length) {
- if (dst == null) {
- throw new NullPointerException("dst");
- }
-
- final byte[] value = this.value;
- final int thisLen = value.length;
-
- if (srcIdx < 0 || length > thisLen - srcIdx) {
- throw new IndexOutOfBoundsException("expected: " + "0 <= srcIdx(" + srcIdx + ") <= srcIdx + length("
- + length + ") <= srcLen(" + thisLen + ')');
- }
-
- dst.setBytes(dstIdx, value, srcIdx, length);
- }
-
- /**
- * Copies the content of this string to a {@link ByteBuf} using {@link ByteBuf#writeBytes(byte[], int, int)}.
- *
- * @param srcIdx the starting offset of characters to copy.
- * @param dst the destination byte array.
- * @param length the number of characters to copy.
- */
- public void copy(int srcIdx, ByteBuf dst, int length) {
- if (dst == null) {
- throw new NullPointerException("dst");
- }
-
- final byte[] value = this.value;
- final int thisLen = value.length;
-
- if (srcIdx < 0 || length > thisLen - srcIdx) {
- throw new IndexOutOfBoundsException("expected: " + "0 <= srcIdx(" + srcIdx + ") <= srcIdx + length("
- + length + ") <= srcLen(" + thisLen + ')');
- }
-
- dst.writeBytes(value, srcIdx, length);
- }
-
- /**
- * Copies the content of this string to a byte array.
- *
- * @param srcIdx the starting offset of characters to copy.
- * @param dst the destination byte array.
- * @param dstIdx the starting offset in the destination byte array.
- * @param length the number of characters to copy.
- */
- public void copy(int srcIdx, byte[] dst, int dstIdx, int length) {
- if (dst == null) {
- throw new NullPointerException("dst");
- }
-
- final byte[] value = this.value;
- final int thisLen = value.length;
-
- if (srcIdx < 0 || length > thisLen - srcIdx) {
- throw new IndexOutOfBoundsException("expected: " + "0 <= srcIdx(" + srcIdx + ") <= srcIdx + length("
- + length + ") <= srcLen(" + thisLen + ')');
- }
-
- System.arraycopy(value, srcIdx, dst, dstIdx, length);
- }
-
/**
* Copied the content of this string to a character array.
*
@@ -795,7 +541,6 @@ public final class AsciiString implements CharSequence, Comparable
throw new NullPointerException("dst");
}
- final byte[] value = this.value;
final int thisLen = value.length;
if (srcIdx < 0 || length > thisLen - srcIdx) {
@@ -805,44 +550,13 @@ public final class AsciiString implements CharSequence, Comparable
final int dstEnd = dstIdx + length;
for (int i = srcIdx, j = dstIdx; j < dstEnd; i++, j++) {
- dst[j] = (char) (value[i] & 0xFF);
+ dst[j] = b2c(value[i]);
}
}
- /**
- * Searches in this string for the first index of the specified character. The search for the character starts at
- * the beginning and moves towards the end of this string.
- *
- * @param c the character to find.
- * @return the index in this string of the specified character, -1 if the character isn't found.
- */
- public int indexOf(int c) {
- return indexOf(c, 0);
- }
-
- /**
- * Searches in this string for the index of the specified character. The search for the character starts at the
- * specified offset and moves towards the end of this string.
- *
- * @param c the character to find.
- * @param start the starting offset.
- * @return the index in this string of the specified character, -1 if the character isn't found.
- */
- public int indexOf(int c, int start) {
- final byte[] value = this.value;
- final int length = value.length;
- if (start < length) {
- if (start < 0) {
- start = 0;
- }
-
- for (int i = start; i < length; i++) {
- if ((value[i] & 0xFF) == c) {
- return i;
- }
- }
- }
- return -1;
+ @Override
+ public AsciiString subSequence(int start, int end) {
+ return (AsciiString) super.subSequence(start, end);
}
/**
@@ -873,7 +587,6 @@ public final class AsciiString implements CharSequence, Comparable
start = 0;
}
- final byte[] value = this.value;
final int thisLen = value.length;
int subCount = subString.length();
@@ -884,56 +597,27 @@ public final class AsciiString implements CharSequence, Comparable
return -1;
}
- char firstChar = subString.charAt(0);
- for (;;) {
- int i = indexOf(firstChar, start);
- if (i == -1 || subCount + i > thisLen) {
- return -1; // handles subCount > count || start >= count
- }
- int o1 = i, o2 = 0;
- while (++o2 < subCount && (value[++o1] & 0xFF) == subString.charAt(o2)) {
- // Intentionally empty
- }
- if (o2 == subCount) {
- return i;
- }
- start = i + 1;
- }
- }
-
- /**
- * Searches in this string for the last index of the specified character. The search for the character starts at the
- * end and moves towards the beginning of this string.
- *
- * @param c the character to find.
- * @return the index in this string of the specified character, -1 if the character isn't found.
- */
- public int lastIndexOf(int c) {
- return lastIndexOf(c, length() - 1);
- }
-
- /**
- * Searches in this string for the index of the specified character. The search for the character starts at the
- * specified offset and moves towards the beginning of this string.
- *
- * @param c the character to find.
- * @param start the starting offset.
- * @return the index in this string of the specified character, -1 if the character isn't found.
- */
- public int lastIndexOf(int c, int start) {
- if (start >= 0) {
- final byte[] value = this.value;
- final int length = value.length;
- if (start >= length) {
- start = length - 1;
- }
- for (int i = start; i >= 0; --i) {
- if ((value[i] & 0xFF) == c) {
+ final char firstChar = subString.charAt(0);
+ ByteProcessor IndexOfVisitor = new IndexOfProcessor((byte) firstChar);
+ try {
+ for (;;) {
+ int i = forEachByte(start, thisLen - start, IndexOfVisitor);
+ if (i == -1 || subCount + i > thisLen) {
+ return -1; // handles subCount > count || start >= count
+ }
+ int o1 = i, o2 = 0;
+ while (++o2 < subCount && b2c(value[++o1]) == subString.charAt(o2)) {
+ // Intentionally empty
+ }
+ if (o2 == subCount) {
return i;
}
+ start = i + 1;
}
+ } catch (Exception e) {
+ PlatformDependent.throwException(e);
+ return -1;
}
- return -1;
}
/**
@@ -961,7 +645,6 @@ public final class AsciiString implements CharSequence, Comparable
* @throws NullPointerException if {@code subString} is {@code null}.
*/
public int lastIndexOf(CharSequence subString, int start) {
- final byte[] value = this.value;
final int thisLen = value.length;
final int subCount = subString.length();
@@ -976,32 +659,29 @@ public final class AsciiString implements CharSequence, Comparable
start = Math.min(start, thisLen - subCount);
// count and subCount are both >= 1
- char firstChar = subString.charAt(0);
- for (;;) {
- int i = lastIndexOf(firstChar, start);
- if (i == -1) {
- return -1;
+ final char firstChar = subString.charAt(0);
+ ByteProcessor IndexOfVisitor = new IndexOfProcessor((byte) firstChar);
+ try {
+ for (;;) {
+ int i = forEachByteDesc(start, thisLen - start, IndexOfVisitor);
+ if (i == -1) {
+ return -1;
+ }
+ int o1 = i, o2 = 0;
+ while (++o2 < subCount && b2c(value[++o1]) == subString.charAt(o2)) {
+ // Intentionally empty
+ }
+ if (o2 == subCount) {
+ return i;
+ }
+ start = i - 1;
}
- int o1 = i, o2 = 0;
- while (++o2 < subCount && (value[++o1] & 0xFF) == subString.charAt(o2)) {
- // Intentionally empty
- }
- if (o2 == subCount) {
- return i;
- }
- start = i - 1;
+ } catch (Exception e) {
+ PlatformDependent.throwException(e);
+ return -1;
}
}
- /**
- * Answers if the size of this String is zero.
- *
- * @return true if the size of this String is zero, false otherwise
- */
- public boolean isEmpty() {
- return value.length == 0;
- }
-
/**
* Compares the specified string to this string and compares the specified range of characters to determine if they
* are the same.
@@ -1022,7 +702,6 @@ public final class AsciiString implements CharSequence, Comparable
return false;
}
- final byte[] value = this.value;
final int thisLen = value.length;
if (thisStart < 0 || thisLen - thisStart < length) {
return false;
@@ -1034,7 +713,7 @@ public final class AsciiString implements CharSequence, Comparable
final int thisEnd = thisStart + length;
for (int i = thisStart, j = start; i < thisEnd; i++, j++) {
- if ((value[i] & 0xFF) != string.charAt(j)) {
+ if (b2c(value[i]) != string.charAt(j)) {
return false;
}
}
@@ -1062,7 +741,6 @@ public final class AsciiString implements CharSequence, Comparable
throw new NullPointerException("string");
}
- final byte[] value = this.value;
final int thisLen = value.length;
if (thisStart < 0 || length > thisLen - thisStart) {
return false;
@@ -1073,7 +751,7 @@ public final class AsciiString implements CharSequence, Comparable
int thisEnd = thisStart + length;
while (thisStart < thisEnd) {
- char c1 = (char) (value[thisStart++] & 0xFF);
+ char c1 = b2c(value[thisStart++]);
char c2 = string.charAt(start++);
if (c1 != c2 && toLowerCase(c1) != toLowerCase(c2)) {
return false;
@@ -1090,18 +768,29 @@ public final class AsciiString implements CharSequence, Comparable
* @return a new string with occurrences of oldChar replaced by newChar.
*/
public AsciiString replace(char oldChar, char newChar) {
- int index = indexOf(oldChar, 0);
+ if (oldChar > MAX_CHAR_VALUE) {
+ return this;
+ }
+
+ final int index;
+ final byte oldCharByte = c2b(oldChar);
+ try {
+ index = forEachByte(new IndexOfProcessor(oldCharByte));
+ } catch (Exception e) {
+ PlatformDependent.throwException(e);
+ return this;
+ }
if (index == -1) {
return this;
}
- final byte[] value = this.value;
final int count = value.length;
+ final byte newCharByte = c2b(newChar);
byte[] buffer = new byte[count];
- for (int i = 0, j = 0; i < value.length; i++, j++) {
+ for (int i = 0, j = 0; i < count; i++, j++) {
byte b = value[i];
- if ((char) (b & 0xFF) == oldChar) {
- b = (byte) newChar;
+ if (b == oldCharByte) {
+ b = newCharByte;
}
buffer[j] = b;
}
@@ -1141,7 +830,6 @@ public final class AsciiString implements CharSequence, Comparable
*/
public AsciiString toLowerCase() {
boolean lowercased = true;
- final byte[] value = this.value;
int i, j;
for (i = 0; i < value.length; ++i) {
byte b = value[i];
@@ -1171,7 +859,6 @@ public final class AsciiString implements CharSequence, Comparable
* @return a new string containing the uppercase characters equivalent to the characters in this string.
*/
public AsciiString toUpperCase() {
- final byte[] value = this.value;
boolean uppercased = true;
int i, j;
for (i = 0; i < value.length; ++i) {
@@ -1202,7 +889,6 @@ public final class AsciiString implements CharSequence, Comparable
* @return a new string with characters {@code <= \\u0020} removed from the beginning and the end.
*/
public AsciiString trim() {
- final byte[] value = this.value;
int start = 0, last = value.length;
int end = last;
while (start <= end && value[start] <= ' ') {
@@ -1283,7 +969,6 @@ public final class AsciiString implements CharSequence, Comparable
final List res = new ArrayList();
int start = 0;
- final byte[] value = this.value;
final int length = value.length;
for (int i = start; i < length; i++) {
if (charAt(i) == delim) {
@@ -1331,155 +1016,70 @@ public final class AsciiString implements CharSequence, Comparable
}
public int parseInt() {
- return parseInt(0, length(), 10);
+ return parseAsciiInt();
}
public int parseInt(int radix) {
- return parseInt(0, length(), radix);
+ return parseAsciiInt(radix);
}
public int parseInt(int start, int end) {
- return parseInt(start, end, 10);
+ return parseAsciiInt(start, end);
}
public int parseInt(int start, int end, int radix) {
- if (radix < Character.MIN_RADIX || radix > Character.MAX_RADIX) {
- throw new NumberFormatException();
- }
-
- if (start == end) {
- throw new NumberFormatException();
- }
-
- int i = start;
- boolean negative = charAt(i) == '-';
- if (negative && ++i == end) {
- throw new NumberFormatException(subSequence(start, end).toString());
- }
-
- return parseInt(i, end, radix, negative);
- }
-
- private int parseInt(int start, int end, int radix, boolean negative) {
- final byte[] value = this.value;
- int max = Integer.MIN_VALUE / radix;
- int result = 0;
- int offset = start;
- while (offset < end) {
- int digit = Character.digit((char) (value[offset++] & 0xFF), radix);
- if (digit == -1) {
- throw new NumberFormatException(subSequence(start, end).toString());
- }
- if (max > result) {
- throw new NumberFormatException(subSequence(start, end).toString());
- }
- int next = result * radix - digit;
- if (next > result) {
- throw new NumberFormatException(subSequence(start, end).toString());
- }
- result = next;
- }
- if (!negative) {
- result = -result;
- if (result < 0) {
- throw new NumberFormatException(subSequence(start, end).toString());
- }
- }
- return result;
+ return parseAsciiInt(start, end, radix);
}
public long parseLong() {
- return parseLong(0, length(), 10);
+ return parseAsciiLong();
}
public long parseLong(int radix) {
- return parseLong(0, length(), radix);
+ return parseAsciiLong(radix);
}
public long parseLong(int start, int end) {
- return parseLong(start, end, 10);
+ return parseAsciiLong(start, end);
}
public long parseLong(int start, int end, int radix) {
- if (radix < Character.MIN_RADIX || radix > Character.MAX_RADIX) {
- throw new NumberFormatException();
- }
-
- if (start == end) {
- throw new NumberFormatException();
- }
-
- int i = start;
- boolean negative = charAt(i) == '-';
- if (negative && ++i == end) {
- throw new NumberFormatException(subSequence(start, end).toString());
- }
-
- return parseLong(i, end, radix, negative);
+ return parseAsciiLong(start, end, radix);
}
- private long parseLong(int start, int end, int radix, boolean negative) {
- final byte[] value = this.value;
- long max = Long.MIN_VALUE / radix;
- long result = 0;
- int offset = start;
- while (offset < end) {
- int digit = Character.digit((char) (value[offset++] & 0xFF), radix);
- if (digit == -1) {
- throw new NumberFormatException(subSequence(start, end).toString());
- }
- if (max > result) {
- throw new NumberFormatException(subSequence(start, end).toString());
- }
- long next = result * radix - digit;
- if (next > result) {
- throw new NumberFormatException(subSequence(start, end).toString());
- }
- result = next;
- }
- if (!negative) {
- result = -result;
- if (result < 0) {
- throw new NumberFormatException(subSequence(start, end).toString());
- }
- }
- return result;
+ public char parseChar(int start) {
+ return charAt(start);
}
public short parseShort() {
- return parseShort(0, length(), 10);
+ return parseAsciiShort();
}
public short parseShort(int radix) {
- return parseShort(0, length(), radix);
+ return parseAsciiShort(radix);
}
public short parseShort(int start, int end) {
- return parseShort(start, end, 10);
+ return parseAsciiShort(start, end);
}
public short parseShort(int start, int end, int radix) {
- int intValue = parseInt(start, end, radix);
- short result = (short) intValue;
- if (result != intValue) {
- throw new NumberFormatException(subSequence(start, end).toString());
- }
- return result;
+ return parseAsciiShort(start, end, radix);
}
public float parseFloat() {
- return parseFloat(0, length());
+ return parseAsciiFloat();
}
public float parseFloat(int start, int end) {
- return Float.parseFloat(toString(start, end));
+ return parseAsciiFloat(start, end);
}
public double parseDouble() {
- return parseDouble(0, length());
+ return parseAsciiDouble();
}
public double parseDouble(int start, int end) {
- return Double.parseDouble(toString(start, end));
+ return parseAsciiDouble(start, end);
}
}
diff --git a/common/src/main/java/io/netty/util/ByteProcessor.java b/common/src/main/java/io/netty/util/ByteProcessor.java
new file mode 100644
index 0000000000..2847813c6f
--- /dev/null
+++ b/common/src/main/java/io/netty/util/ByteProcessor.java
@@ -0,0 +1,128 @@
+/*
+ * Copyright 2015 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.util;
+
+/**
+ * Provides a mechanism to iterate over a collection of bytes.
+ */
+public interface ByteProcessor {
+ /**
+ * A {@link ByteProcessor} which finds the first appearance of a specific byte.
+ */
+ class IndexOfProcessor implements ByteProcessor {
+ private final byte byteToFind;
+
+ public IndexOfProcessor(byte byteToFind) {
+ this.byteToFind = byteToFind;
+ }
+
+ @Override
+ public boolean process(byte value) {
+ return value != byteToFind;
+ }
+ }
+
+ /**
+ * A {@link ByteProcessor} which finds the first appearance which is not of a specific byte.
+ */
+ class IndexNotOfProcessor implements ByteProcessor {
+ private final byte byteToNotFind;
+
+ public IndexNotOfProcessor(byte byteToNotFind) {
+ this.byteToNotFind = byteToNotFind;
+ }
+
+ @Override
+ public boolean process(byte value) {
+ return value == byteToNotFind;
+ }
+ }
+
+ /**
+ * Aborts on a {@code NUL (0x00)}.
+ */
+ ByteProcessor FIND_NUL = new IndexOfProcessor((byte) 0);
+
+ /**
+ * Aborts on a non-{@code NUL (0x00)}.
+ */
+ ByteProcessor FIND_NON_NUL = new IndexNotOfProcessor((byte) 0);
+
+ /**
+ * Aborts on a {@code CR ('\r')}.
+ */
+ ByteProcessor FIND_CR = new IndexOfProcessor((byte) '\r');
+
+ /**
+ * Aborts on a non-{@code CR ('\r')}.
+ */
+ ByteProcessor FIND_NON_CR = new IndexNotOfProcessor((byte) '\r');
+
+ /**
+ * Aborts on a {@code LF ('\n')}.
+ */
+ ByteProcessor FIND_LF = new IndexOfProcessor((byte) '\n');
+
+ /**
+ * Aborts on a non-{@code LF ('\n')}.
+ */
+ ByteProcessor FIND_NON_LF = new IndexNotOfProcessor((byte) '\n');
+
+ /**
+ * Aborts on a {@code CR ('\r')} or a {@code LF ('\n')}.
+ */
+ ByteProcessor FIND_CRLF = new ByteProcessor() {
+ @Override
+ public boolean process(byte value) throws Exception {
+ return value != '\r' && value != '\n';
+ }
+ };
+
+ /**
+ * Aborts on a byte which is neither a {@code CR ('\r')} nor a {@code LF ('\n')}.
+ */
+ ByteProcessor FIND_NON_CRLF = new ByteProcessor() {
+ @Override
+ public boolean process(byte value) throws Exception {
+ return value == '\r' || value == '\n';
+ }
+ };
+
+ /**
+ * Aborts on a linear whitespace (a ({@code ' '} or a {@code '\t'}).
+ */
+ ByteProcessor FIND_LINEAR_WHITESPACE = new ByteProcessor() {
+ @Override
+ public boolean process(byte value) throws Exception {
+ return value != ' ' && value != '\t';
+ }
+ };
+
+ /**
+ * Aborts on a byte which is not a linear whitespace (neither {@code ' '} nor {@code '\t'}).
+ */
+ ByteProcessor FIND_NON_LINEAR_WHITESPACE = new ByteProcessor() {
+ @Override
+ public boolean process(byte value) throws Exception {
+ return value == ' ' || value == '\t';
+ }
+ };
+
+ /**
+ * @return {@code true} if the processor wants to continue the loop and handle the next byte in the buffer.
+ * {@code false} if the processor wants to stop handling bytes and abort the loop.
+ */
+ boolean process(byte value) throws Exception;
+}
diff --git a/common/src/main/java/io/netty/util/ByteString.java b/common/src/main/java/io/netty/util/ByteString.java
new file mode 100644
index 0000000000..258dcca610
--- /dev/null
+++ b/common/src/main/java/io/netty/util/ByteString.java
@@ -0,0 +1,660 @@
+/*
+ * Copyright 2015 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.util;
+
+import static io.netty.util.internal.ObjectUtil.checkNotNull;
+import io.netty.util.internal.StringUtil;
+
+import java.nio.ByteBuffer;
+import java.nio.CharBuffer;
+import java.nio.charset.Charset;
+import java.nio.charset.CharsetEncoder;
+import java.util.Arrays;
+import java.util.Comparator;
+
+/**
+ * The primary use case for this class is to function as an immutable array of bytes. For performance reasons this
+ * class supports sharing memory with external arrays, and also direct access to the underlying memory via
+ * {@link #array()}. Care must be taken when directly accessing the memory as that may invalidate assumptions that
+ * this object is immutable.
+ */
+public class ByteString {
+ /**
+ * A byte wise comparator between two {@link ByteString} objects.
+ */
+ public static final Comparator DEFAULT_COMPARATOR = new Comparator() {
+ @Override
+ public int compare(ByteString o1, ByteString o2) {
+ if (o1 == o2) {
+ return 0;
+ }
+
+ int result;
+ int length1 = o1.length();
+ int length2 = o2.length();
+ int minLength = Math.min(length1, length2);
+ for (int i = 0, j = 0; j < minLength; i++, j++) {
+ result = o1.value[i] - o2.value[j];
+ if (result != 0) {
+ return result;
+ }
+ }
+
+ return length1 - length2;
+ }
+ };
+ public static final ByteString EMPTY_STRING = new ByteString(0);
+ protected static final int HASH_CODE_PRIME = 31;
+
+ /**
+ * If this value is modified outside the constructor then call {@link #arrayChanged()}.
+ */
+ protected final byte[] value;
+ /**
+ * The hash code is cached after it is first computed. It can be reset with {@link #arrayChanged()}.
+ */
+ private int hash;
+
+ /**
+ * Used for classes which extend this class and want to initialize the {@link #value} array by them selves.
+ */
+ ByteString(int length) { value = new byte[length]; }
+
+ /**
+ * Initialize this byte string based upon a byte array. A copy will be made.
+ */
+ public ByteString(byte[] value) {
+ this(value, true);
+ }
+
+ /**
+ * Initialize this byte string based upon a byte array.
+ * {@code copy} determines if a copy is made or the array is shared.
+ */
+ public ByteString(byte[] value, boolean copy) {
+ if (copy) {
+ this.value = checkNotNull(value, "value").clone();
+ } else {
+ this.value = checkNotNull(value, "value");
+ }
+ }
+
+ /**
+ * Initialize this byte string based upon a range of a byte array. A copy will be made.
+ */
+ public ByteString(byte[] value, int start, int length) {
+ this(value, start, length, true);
+ }
+
+ /**
+ * Construct a new {@link BinaryString} object from a {@code byte[]} array.
+ * @param copy {@code true} then a copy of the memory will be made. {@code false} the underlying memory
+ * will be shared. If this shared memory changes then {@link #arrayChanged()} must be called.
+ */
+ public ByteString(byte[] value, int start, int length, boolean copy) {
+ if (start < 0 || start > checkNotNull(value, "value").length - length) {
+ throw new IndexOutOfBoundsException("expected: " + "0 <= start(" + start + ") <= start + length(" + length
+ + ") <= " + "value.length(" + value.length + ')');
+ }
+
+ if (copy || start != 0 || length != value.length) {
+ this.value = Arrays.copyOfRange(value, start, start + length);
+ } else {
+ this.value = value;
+ }
+ }
+
+ /**
+ * Create a copy of the underlying storage from {@link value}.
+ * The copy will start at {@link ByteBuffer#position()} and copy {@link ByteBuffer#remaining()} bytes.
+ */
+ public ByteString(ByteBuffer value) {
+ this.value = getBytes(value);
+ }
+
+ /**
+ * Create a copy of the underlying storage from {@link value}.
+ * The copy will start at {@code start} and copy {@code length} bytes.
+ */
+ public ByteString(ByteBuffer value, int start, int length) {
+ this.value = getBytes(value, start, length, true);
+ }
+
+ /**
+ * Initialize a {@link ByteString} based upon the underlying storage from {@link value}.
+ * The copy will start at {@code start} and copy {@code length} bytes.
+ * if {@code copy} is true a copy will be made of the memory.
+ * if {@code copy} is false the underlying storage will be shared, if possible.
+ */
+ public ByteString(ByteBuffer value, int start, int length, boolean copy) {
+ this.value = getBytes(value, start, length, copy);
+ }
+
+ /**
+ * Create a copy of {@link value} into a {@link ByteString} using the encoding type of {@code charset}.
+ */
+ public ByteString(char[] value, Charset charset) {
+ this.value = getBytes(value, charset);
+ }
+
+ /**
+ * Create a copy of {@link value} into a {@link ByteString} using the encoding type of {@code charset}.
+ * The copy will start at index {@code start} and copy {@code length} bytes.
+ */
+ public ByteString(char[] value, Charset charset, int start, int length) {
+ this.value = getBytes(value, charset, start, length);
+ }
+
+ /**
+ * Create a copy of {@link value} into a {@link ByteString} using the encoding type of {@code charset}.
+ */
+ public ByteString(CharSequence value, Charset charset) {
+ this.value = getBytes(value, charset);
+ }
+
+ /**
+ * Create a copy of {@link value} into a {@link ByteString} using the encoding type of {@code charset}.
+ * The copy will start at index {@code start} and copy {@code length} bytes.
+ */
+ public ByteString(CharSequence value, Charset charset, int start, int length) {
+ this.value = getBytes(value, charset, start, length);
+ }
+
+ /**
+ * Create a copy of the underlying storage from {@link value} into a byte array.
+ * The copy will start at {@link ByteBuffer#position()} and copy {@link ByteBuffer#remaining()} bytes.
+ */
+ private static byte[] getBytes(ByteBuffer value) {
+ return getBytes(value, value.position(), checkNotNull(value, "value").remaining());
+ }
+
+ /**
+ * Create a copy of the underlying storage from {@link value} into a byte array.
+ * The copy will start at {@code start} and copy {@code length} bytes.
+ */
+ private static byte[] getBytes(ByteBuffer value, int start, int length) {
+ return getBytes(value, start, length, true);
+ }
+
+ /**
+ * Return an array of the underlying storage from {@link value} into a byte array.
+ * The copy will start at {@code start} and copy {@code length} bytes.
+ * if {@code copy} is true a copy will be made of the memory.
+ * if {@code copy} is false the underlying storage will be shared, if possible.
+ */
+ private static byte[] getBytes(ByteBuffer value, int start, int length, boolean copy) {
+ if (start < 0 || length > checkNotNull(value, "value").capacity() - start) {
+ throw new IndexOutOfBoundsException("expected: " + "0 <= start(" + start + ") <= start + length(" + length
+ + ") <= " + "value.capacity(" + value.capacity() + ')');
+ }
+
+ if (value.hasArray()) {
+ if (copy || start != 0 || length != value.capacity()) {
+ int baseOffset = value.arrayOffset() + start;
+ return Arrays.copyOfRange(value.array(), baseOffset, baseOffset + length);
+ } else {
+ return value.array();
+ }
+ }
+
+ byte[] v = new byte[length];
+ int oldPos = value.position();
+ value.get(v, 0, length);
+ value.position(oldPos);
+ return v;
+ }
+
+ /**
+ * Create a copy of {@link value} into a byte array using the encoding type of {@code charset}.
+ */
+ private static byte[] getBytes(char[] value, Charset charset) {
+ return getBytes(value, charset, 0, checkNotNull(value, "value").length);
+ }
+
+ /**
+ * Create a copy of {@link value} into a byte array using the encoding type of {@code charset}.
+ * The copy will start at index {@code start} and copy {@code length} bytes.
+ */
+ private static byte[] getBytes(char[] value, Charset charset, int start, int length) {
+ if (start < 0 || length > checkNotNull(value, "value").length - start) {
+ throw new IndexOutOfBoundsException("expected: " + "0 <= start(" + start + ") <= start + length(" + length
+ + ") <= " + "length(" + length + ')');
+ }
+
+ CharBuffer cbuf = CharBuffer.wrap(value, start, start + length);
+ CharsetEncoder encoder = CharsetUtil.getEncoder(charset);
+ ByteBuffer nativeBuffer = ByteBuffer.allocate((int) (encoder.maxBytesPerChar() * length));
+ encoder.encode(cbuf, nativeBuffer, true);
+ final int offset = nativeBuffer.arrayOffset();
+ return Arrays.copyOfRange(nativeBuffer.array(), offset, offset + nativeBuffer.position());
+ }
+
+ /**
+ * Create a copy of {@link value} into a byte array using the encoding type of {@code charset}.
+ */
+ private static byte[] getBytes(CharSequence value, Charset charset) {
+ return getBytes(value, charset, 0, checkNotNull(value, "value").length());
+ }
+
+ /**
+ * Create a copy of {@link value} into a byte array using the encoding type of {@code charset}.
+ * The copy will start at index {@code start} and copy {@code length} bytes.
+ */
+ private static byte[] getBytes(CharSequence value, Charset charset, int start, int length) {
+ if (start < 0 || length > checkNotNull(value, "value").length() - start) {
+ throw new IndexOutOfBoundsException("expected: " + "0 <= start(" + start + ") <= start + length(" + length
+ + ") <= " + "length(" + value.length() + ')');
+ }
+
+ CharBuffer cbuf = CharBuffer.wrap(value, start, start + length);
+ CharsetEncoder encoder = CharsetUtil.getEncoder(charset);
+ ByteBuffer nativeBuffer = ByteBuffer.allocate((int) (encoder.maxBytesPerChar() * length));
+ encoder.encode(cbuf, nativeBuffer, true);
+ final int offset = nativeBuffer.arrayOffset();
+ return Arrays.copyOfRange(nativeBuffer.array(), offset, offset + nativeBuffer.position());
+ }
+
+ /**
+ * 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.
+ * The last-visited index If the {@link ByteProcessor#process(byte)} returned {@code false}.
+ */
+ public final int forEachByte(ByteProcessor visitor) throws Exception {
+ return forEachByte(0, value.length, visitor);
+ }
+
+ /**
+ * Iterates over the specified area of this buffer with the specified {@code processor} in ascending order.
+ * (i.e. {@code index}, {@code (index + 1)}, .. {@code (index + length - 1)}).
+ *
+ * @return {@code -1} if the processor iterated to or beyond the end of the specified area.
+ * The last-visited index If the {@link ByteProcessor#process(byte)} returned {@code false}.
+ */
+ public final int forEachByte(int index, int length, ByteProcessor visitor) throws Exception {
+ if (index < 0 || length > value.length - index) {
+ throw new IndexOutOfBoundsException("expected: " + "0 <= index(" + index + ") <= start + length(" + length
+ + ") <= " + "length(" + value.length + ')');
+ }
+
+ for (int i = index; i < length; ++i) {
+ if (!visitor.process(value[i])) {
+ return i;
+ }
+ }
+ return -1;
+ }
+
+ /**
+ * 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.
+ * The last-visited index If the {@link ByteProcessor#process(byte)} returned {@code false}.
+ */
+ public final int forEachByteDesc(ByteProcessor visitor) throws Exception {
+ return forEachByteDesc(0, length(), visitor);
+ }
+
+ /**
+ * Iterates over the specified area of this buffer with the specified {@code processor} in descending order.
+ * (i.e. {@code (index + length - 1)}, {@code (index + length - 2)}, ... {@code index}).
+ *
+ * @return {@code -1} if the processor iterated to or beyond the beginning of the specified area.
+ * The last-visited index If the {@link ByteProcessor#process(byte)} returned {@code false}.
+ */
+ public final int forEachByteDesc(int index, int length, ByteProcessor visitor) throws Exception {
+ if (index < 0 || length > value.length - index) {
+ throw new IndexOutOfBoundsException("expected: " + "0 <= index(" + index + ") <= start + length(" + length
+ + ") <= " + "length(" + value.length + ')');
+ }
+
+ for (int i = index + length - 1; i >= index; --i) {
+ if (!visitor.process(value[i])) {
+ return i;
+ }
+ }
+ return -1;
+ }
+
+ public final byte byteAt(int index) {
+ return value[index];
+ }
+
+ public final boolean isEmpty() {
+ return value.length == 0;
+ }
+
+ public final int length() {
+ return value.length;
+ }
+
+ /**
+ * During normal use cases the {@link ByteString} should be immutable, but if the underlying array is shared,
+ * and changes then this needs to be called.
+ */
+ public final void arrayChanged() {
+ hash = 0;
+ }
+
+ /**
+ * This gives direct access to the underlying storage array.
+ * The {@link #toByteArray()} should be preferred over this method.
+ * If the return value is changed then {@link #arrayChanged()} must be called.
+ */
+ public final byte[] array() {
+ return value;
+ }
+
+ /**
+ * Converts this string to a byte array.
+ */
+ public final byte[] toByteArray() {
+ return toByteArray(0, length());
+ }
+
+ /**
+ * Converts a subset of this string to a byte array.
+ * The subset is defined by the range [{@code start}, {@code end}).
+ */
+ public final byte[] toByteArray(int start, int end) {
+ return Arrays.copyOfRange(value, start, end);
+ }
+
+ /**
+ * Copies the content of this string to a byte array.
+ *
+ * @param srcIdx the starting offset of characters to copy.
+ * @param dst the destination byte array.
+ * @param dstIdx the starting offset in the destination byte array.
+ * @param length the number of characters to copy.
+ */
+ public final void copy(int srcIdx, byte[] dst, int dstIdx, int length) {
+ final int thisLen = value.length;
+
+ if (srcIdx < 0 || length > thisLen - srcIdx) {
+ throw new IndexOutOfBoundsException("expected: " + "0 <= srcIdx(" + srcIdx + ") <= srcIdx + length("
+ + length + ") <= srcLen(" + thisLen + ')');
+ }
+
+ System.arraycopy(value, srcIdx, checkNotNull(dst, "dst"), dstIdx, length);
+ }
+
+ @Override
+ public int hashCode() {
+ if (hash != 0) {
+ return hash;
+ }
+
+ for (int i = 0; i < value.length; ++i) {
+ hash = hash * HASH_CODE_PRIME ^ value[i] & HASH_CODE_PRIME;
+ }
+
+ return hash;
+ }
+
+ /**
+ * Copies a range of characters into a new string.
+ *
+ * @param start the offset of the first character.
+ * @return a new string containing the characters from start to the end of the string.
+ * @throws IndexOutOfBoundsException if {@code start < 0} or {@code start > length()}.
+ */
+ public final ByteString subSequence(int start) {
+ return subSequence(start, length());
+ }
+
+ public ByteString subSequence(int start, int end) {
+ if (start < 0 || start > end || end > length()) {
+ throw new IndexOutOfBoundsException("expected: 0 <= start(" + start + ") <= end (" + end + ") <= length("
+ + length() + ')');
+ }
+
+ if (start == 0 && end == value.length) {
+ return this;
+ }
+
+ if (end == start) {
+ return EMPTY_STRING;
+ }
+
+ return new ByteString(value, start, end - start, false);
+ }
+
+ public final int parseAsciiInt() {
+ return parseAsciiInt(0, length(), 10);
+ }
+
+ public final int parseAsciiInt(int radix) {
+ return parseAsciiInt(0, length(), radix);
+ }
+
+ public final int parseAsciiInt(int start, int end) {
+ return parseAsciiInt(start, end, 10);
+ }
+
+ public final int parseAsciiInt(int start, int end, int radix) {
+ if (radix < Character.MIN_RADIX || radix > Character.MAX_RADIX) {
+ throw new NumberFormatException();
+ }
+
+ if (start == end) {
+ throw new NumberFormatException();
+ }
+
+ int i = start;
+ boolean negative = byteAt(i) == '-';
+ if (negative && ++i == end) {
+ throw new NumberFormatException(subSequence(start, end).toString());
+ }
+
+ return parseAsciiInt(i, end, radix, negative);
+ }
+
+ private int parseAsciiInt(int start, int end, int radix, boolean negative) {
+ int max = Integer.MIN_VALUE / radix;
+ int result = 0;
+ int offset = start;
+ while (offset < end) {
+ int digit = Character.digit((char) (value[offset++] & 0xFF), radix);
+ if (digit == -1) {
+ throw new NumberFormatException(subSequence(start, end).toString());
+ }
+ if (max > result) {
+ throw new NumberFormatException(subSequence(start, end).toString());
+ }
+ int next = result * radix - digit;
+ if (next > result) {
+ throw new NumberFormatException(subSequence(start, end).toString());
+ }
+ result = next;
+ }
+ if (!negative) {
+ result = -result;
+ if (result < 0) {
+ throw new NumberFormatException(subSequence(start, end).toString());
+ }
+ }
+ return result;
+ }
+
+ public final long parseAsciiLong() {
+ return parseAsciiLong(0, length(), 10);
+ }
+
+ public final long parseAsciiLong(int radix) {
+ return parseAsciiLong(0, length(), radix);
+ }
+
+ public final long parseAsciiLong(int start, int end) {
+ return parseAsciiLong(start, end, 10);
+ }
+
+ public final long parseAsciiLong(int start, int end, int radix) {
+ if (radix < Character.MIN_RADIX || radix > Character.MAX_RADIX) {
+ throw new NumberFormatException();
+ }
+
+ if (start == end) {
+ throw new NumberFormatException();
+ }
+
+ int i = start;
+ boolean negative = byteAt(i) == '-';
+ if (negative && ++i == end) {
+ throw new NumberFormatException(subSequence(start, end).toString());
+ }
+
+ return parseAsciiLong(i, end, radix, negative);
+ }
+
+ private long parseAsciiLong(int start, int end, int radix, boolean negative) {
+ long max = Long.MIN_VALUE / radix;
+ long result = 0;
+ int offset = start;
+ while (offset < end) {
+ int digit = Character.digit((char) (value[offset++] & 0xFF), radix);
+ if (digit == -1) {
+ throw new NumberFormatException(subSequence(start, end).toString());
+ }
+ if (max > result) {
+ throw new NumberFormatException(subSequence(start, end).toString());
+ }
+ long next = result * radix - digit;
+ if (next > result) {
+ throw new NumberFormatException(subSequence(start, end).toString());
+ }
+ result = next;
+ }
+ if (!negative) {
+ result = -result;
+ if (result < 0) {
+ throw new NumberFormatException(subSequence(start, end).toString());
+ }
+ }
+ return result;
+ }
+
+ public final char parseChar() {
+ return parseChar(0);
+ }
+
+ public char parseChar(int start) {
+ if (start + 1 >= value.length) {
+ throw new IndexOutOfBoundsException("2 bytes required to convert to character. index " +
+ start + " would go out of bounds.");
+ }
+ return (char) (((value[start] & 0xFF) << 8) | (value[start + 1] & 0xFF));
+ }
+
+ public final short parseAsciiShort() {
+ return parseAsciiShort(0, length(), 10);
+ }
+
+ public final short parseAsciiShort(int radix) {
+ return parseAsciiShort(0, length(), radix);
+ }
+
+ public final short parseAsciiShort(int start, int end) {
+ return parseAsciiShort(start, end, 10);
+ }
+
+ public final short parseAsciiShort(int start, int end, int radix) {
+ int intValue = parseAsciiInt(start, end, radix);
+ short result = (short) intValue;
+ if (result != intValue) {
+ throw new NumberFormatException(subSequence(start, end).toString());
+ }
+ return result;
+ }
+
+ public final float parseAsciiFloat() {
+ return parseAsciiFloat(0, length());
+ }
+
+ public final float parseAsciiFloat(int start, int end) {
+ return Float.parseFloat(toString(start, end));
+ }
+
+ public final double parseAsciiDouble() {
+ return parseAsciiDouble(0, length());
+ }
+
+ public final double parseAsciiDouble(int start, int end) {
+ return Double.parseDouble(toString(start, end));
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (!(obj instanceof ByteString)) {
+ return false;
+ }
+
+ if (this == obj) {
+ return true;
+ }
+
+ ByteString that = (ByteString) obj;
+ if (length() != that.length() || hashCode() != that.hashCode()) {
+ return false;
+ }
+
+ final int end = value.length;
+ for (int i = 0, j = 0; i < end; i++, j++) {
+ if (value[i] != that.value[j]) {
+ return false;
+ }
+ }
+
+ return true;
+ }
+
+ /**
+ * Translates the entire byte string to a {@link String}.
+ * @see {@link #toString(int, int)}
+ */
+ @Override
+ public String toString() {
+ return toString(0, length());
+ }
+
+ /**
+ * Translates the entire byte string to a {@link String} using the {@code charset} encoding.
+ * @see {@link #toString(Charset, int, int)}
+ */
+ public final String toString(Charset charset) {
+ return toString(charset, 0, length());
+ }
+
+ /**
+ * Translates the [{@code start}, {@code end}) range of this byte string to a {@link String}.
+ * @see {@link #toString(Charset, int, int)}
+ */
+ public final String toString(int start, int end) {
+ return toString(CharsetUtil.ISO_8859_1, start, end);
+ }
+
+ /**
+ * Translates the [{@code start}, {@code end}) range of this byte string to a {@link String}
+ * using the {@code charset} encoding.
+ */
+ public String toString(Charset charset, int start, int end) {
+ int length = end - start;
+ if (length == 0) {
+ return StringUtil.EMPTY_STRING;
+ }
+
+ return new String(value, start, length, charset);
+ }
+}
diff --git a/common/src/main/java/io/netty/util/internal/StringUtil.java b/common/src/main/java/io/netty/util/internal/StringUtil.java
index ca69b8f707..3d743d6876 100644
--- a/common/src/main/java/io/netty/util/internal/StringUtil.java
+++ b/common/src/main/java/io/netty/util/internal/StringUtil.java
@@ -34,6 +34,7 @@ public final class StringUtil {
public static final char LINE_FEED = '\n';
public static final char CARRIAGE_RETURN = '\r';
public static final String EMPTY_STRING = "";
+ public static final byte UPPER_CASE_TO_LOWER_CASE_ASCII_OFFSET = (int) 'a' - (int) 'A';
private static final String[] BYTE2HEX_PAD = new String[256];
private static final String[] BYTE2HEX_NOPAD = new String[256];
/**
diff --git a/codec/src/test/java/io/netty/handler/codec/AsciiStringTest.java b/common/src/test/java/io/netty/util/AsciiStringTest.java
similarity index 69%
rename from codec/src/test/java/io/netty/handler/codec/AsciiStringTest.java
rename to common/src/test/java/io/netty/util/AsciiStringTest.java
index 0d459bc1fc..f21b046245 100644
--- a/codec/src/test/java/io/netty/handler/codec/AsciiStringTest.java
+++ b/common/src/test/java/io/netty/util/AsciiStringTest.java
@@ -13,15 +13,11 @@
* License for the specific language governing permissions and limitations
* under the License.
*/
-package io.netty.handler.codec;
+package io.netty.util;
import static org.junit.Assert.assertArrayEquals;
-import io.netty.util.CharsetUtil;
-import java.nio.ByteBuffer;
-import java.nio.CharBuffer;
import java.nio.charset.Charset;
-import java.nio.charset.CharsetEncoder;
import org.junit.Assert;
import org.junit.Test;
@@ -41,8 +37,8 @@ public class AsciiStringTest {
final Charset[] charsets = CharsetUtil.values();
for (int i = 0; i < charsets.length; ++i) {
final Charset charset = charsets[i];
- byte[] expected = getBytesWithEncoder(bString, charset);
- byte[] actual = AsciiString.getBytes(b, charset);
+ byte[] expected = bString.getBytes(charset);
+ byte[] actual = new ByteString(b, charset).toByteArray();
assertArrayEquals("failure for " + charset, expected, actual);
}
}
@@ -58,7 +54,7 @@ public class AsciiStringTest {
for (int i = 0; i < charsets.length; ++i) {
final Charset charset = charsets[i];
byte[] expected = bString.getBytes(charset);
- byte[] actual = AsciiString.getBytes(bString, charset);
+ byte[] actual = new ByteString(bString, charset).toByteArray();
assertArrayEquals("failure for " + charset, expected, actual);
}
}
@@ -72,12 +68,8 @@ public class AsciiStringTest {
final String bString = b.toString();
// The AsciiString class actually limits the Charset to ISO_8859_1
byte[] expected = bString.getBytes(CharsetUtil.ISO_8859_1);
- final Charset[] charsets = CharsetUtil.values();
- for (int i = 0; i < charsets.length; ++i) {
- final Charset charset = charsets[i];
- byte[] actual = AsciiString.getBytes(new AsciiString(bString), charset);
- assertArrayEquals("failure for " + charset, expected, actual);
- }
+ byte[] actual = new AsciiString(bString).toByteArray();
+ assertArrayEquals(expected, actual);
}
@Test
@@ -86,11 +78,4 @@ public class AsciiStringTest {
AsciiString ascii = new AsciiString(string.toCharArray());
Assert.assertEquals(string, ascii.toString());
}
-
- private static byte[] getBytesWithEncoder(CharSequence value, Charset charset) {
- final CharsetEncoder encoder = CharsetUtil.getEncoder(charset);
- final ByteBuffer nativeBuffer = ByteBuffer.allocate((int) (encoder.maxBytesPerChar() * value.length()));
- encoder.encode(CharBuffer.wrap(value), nativeBuffer, true);
- return nativeBuffer.array();
- }
}
diff --git a/example/src/main/java/io/netty/example/http/helloworld/HttpHelloWorldServerHandler.java b/example/src/main/java/io/netty/example/http/helloworld/HttpHelloWorldServerHandler.java
index 2999f302e9..e56b3b1f25 100644
--- a/example/src/main/java/io/netty/example/http/helloworld/HttpHelloWorldServerHandler.java
+++ b/example/src/main/java/io/netty/example/http/helloworld/HttpHelloWorldServerHandler.java
@@ -19,12 +19,11 @@ import io.netty.buffer.Unpooled;
import io.netty.channel.ChannelFutureListener;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelInboundHandlerAdapter;
-import io.netty.handler.codec.AsciiString;
import io.netty.handler.codec.http.DefaultFullHttpResponse;
import io.netty.handler.codec.http.FullHttpResponse;
import io.netty.handler.codec.http.HttpHeaderUtil;
import io.netty.handler.codec.http.HttpRequest;
-
+import io.netty.util.AsciiString;
import static io.netty.handler.codec.http.HttpResponseStatus.*;
import static io.netty.handler.codec.http.HttpVersion.*;
diff --git a/example/src/main/java/io/netty/example/http2/server/HelloWorldHttp2Handler.java b/example/src/main/java/io/netty/example/http2/server/HelloWorldHttp2Handler.java
index 5850b7c0b6..61fff9e4b9 100644
--- a/example/src/main/java/io/netty/example/http2/server/HelloWorldHttp2Handler.java
+++ b/example/src/main/java/io/netty/example/http2/server/HelloWorldHttp2Handler.java
@@ -22,7 +22,6 @@ import static io.netty.handler.codec.http.HttpResponseStatus.OK;
import static io.netty.handler.logging.LogLevel.INFO;
import io.netty.buffer.ByteBuf;
import io.netty.channel.ChannelHandlerContext;
-import io.netty.handler.codec.AsciiString;
import io.netty.handler.codec.http.HttpServerUpgradeHandler;
import io.netty.handler.codec.http2.DefaultHttp2Connection;
import io.netty.handler.codec.http2.DefaultHttp2FrameReader;
@@ -39,6 +38,7 @@ import io.netty.handler.codec.http2.Http2FrameWriter;
import io.netty.handler.codec.http2.Http2Headers;
import io.netty.handler.codec.http2.Http2InboundFrameLogger;
import io.netty.handler.codec.http2.Http2OutboundFrameLogger;
+import io.netty.util.AsciiString;
import io.netty.util.CharsetUtil;
/**
diff --git a/handler-proxy/src/main/java/io/netty/handler/proxy/HttpProxyHandler.java b/handler-proxy/src/main/java/io/netty/handler/proxy/HttpProxyHandler.java
index 527d238c3c..2008f3b1e0 100644
--- a/handler-proxy/src/main/java/io/netty/handler/proxy/HttpProxyHandler.java
+++ b/handler-proxy/src/main/java/io/netty/handler/proxy/HttpProxyHandler.java
@@ -20,7 +20,6 @@ import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelPipeline;
-import io.netty.handler.codec.AsciiString;
import io.netty.handler.codec.base64.Base64;
import io.netty.handler.codec.http.DefaultFullHttpRequest;
import io.netty.handler.codec.http.FullHttpRequest;
@@ -31,6 +30,7 @@ import io.netty.handler.codec.http.HttpResponse;
import io.netty.handler.codec.http.HttpResponseStatus;
import io.netty.handler.codec.http.HttpVersion;
import io.netty.handler.codec.http.LastHttpContent;
+import io.netty.util.AsciiString;
import io.netty.util.CharsetUtil;
import java.net.InetSocketAddress;
diff --git a/microbench/src/test/java/io/netty/microbench/http2/Http2FrameWriterBenchmark.java b/microbench/src/test/java/io/netty/microbench/http2/Http2FrameWriterBenchmark.java
index 576161c673..a4ac332a76 100644
--- a/microbench/src/test/java/io/netty/microbench/http2/Http2FrameWriterBenchmark.java
+++ b/microbench/src/test/java/io/netty/microbench/http2/Http2FrameWriterBenchmark.java
@@ -43,7 +43,6 @@ import io.netty.channel.socket.nio.NioServerSocketChannel;
import io.netty.channel.socket.nio.NioSocketChannel;
import io.netty.channel.socket.oio.OioServerSocketChannel;
import io.netty.channel.socket.oio.OioSocketChannel;
-import io.netty.handler.codec.AsciiString;
import io.netty.handler.codec.http2.DefaultHttp2Connection;
import io.netty.handler.codec.http2.DefaultHttp2ConnectionDecoder;
import io.netty.handler.codec.http2.DefaultHttp2ConnectionEncoder;
@@ -61,6 +60,7 @@ import io.netty.handler.codec.http2.Http2LocalFlowController;
import io.netty.handler.codec.http2.Http2RemoteFlowController;
import io.netty.microbench.channel.EmbeddedChannelWriteReleaseHandlerContext;
import io.netty.microbench.util.AbstractSharedExecutorMicrobenchmark;
+import io.netty.util.AsciiString;
import io.netty.util.concurrent.Future;
import java.net.InetSocketAddress;