HttpResponseStatus object allocation reduction
Motivation: Usages of HttpResponseStatus may result in more object allocation then necessary due to not looking for cached objects and the AsciiString parsing method not being used due to CharSequence method being used instead. Modifications: - HttpResponseDecoder should attempt to get the HttpResponseStatus from cache instead of allocating a new object - HttpResponseStatus#parseLine(CharSequence) should check if the type is AsciiString and redirect to the AsciiString parsing method which may not require an additional toString call - HttpResponseStatus#parseLine(AsciiString) can be optimized and doesn't require and may not require object allocation Result: Less allocations when dealing with HttpResponseStatus.
This commit is contained in:
parent
b769ec0934
commit
4921f62c8a
@ -37,6 +37,7 @@ public class ByteProcessorTest {
|
|||||||
assertEquals(16, buf.forEachByte(14, length - 14, ByteProcessor.FIND_NON_LF));
|
assertEquals(16, buf.forEachByte(14, length - 14, ByteProcessor.FIND_NON_LF));
|
||||||
assertEquals(19, buf.forEachByte(16, length - 16, ByteProcessor.FIND_NUL));
|
assertEquals(19, buf.forEachByte(16, length - 16, ByteProcessor.FIND_NUL));
|
||||||
assertEquals(21, buf.forEachByte(19, length - 19, ByteProcessor.FIND_NON_NUL));
|
assertEquals(21, buf.forEachByte(19, length - 19, ByteProcessor.FIND_NON_NUL));
|
||||||
|
assertEquals(24, buf.forEachByte(19, length - 19, ByteProcessor.FIND_ASCII_SPACE));
|
||||||
assertEquals(24, buf.forEachByte(21, length - 21, ByteProcessor.FIND_LINEAR_WHITESPACE));
|
assertEquals(24, buf.forEachByte(21, length - 21, ByteProcessor.FIND_LINEAR_WHITESPACE));
|
||||||
assertEquals(28, buf.forEachByte(24, length - 24, ByteProcessor.FIND_NON_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));
|
assertEquals(-1, buf.forEachByte(28, length - 28, ByteProcessor.FIND_LINEAR_WHITESPACE));
|
||||||
@ -51,6 +52,7 @@ public class ByteProcessorTest {
|
|||||||
final int length = buf.readableBytes();
|
final int length = buf.readableBytes();
|
||||||
|
|
||||||
assertEquals(27, buf.forEachByteDesc(0, length, ByteProcessor.FIND_LINEAR_WHITESPACE));
|
assertEquals(27, buf.forEachByteDesc(0, length, ByteProcessor.FIND_LINEAR_WHITESPACE));
|
||||||
|
assertEquals(25, buf.forEachByteDesc(0, length, ByteProcessor.FIND_ASCII_SPACE));
|
||||||
assertEquals(23, buf.forEachByteDesc(0, 28, ByteProcessor.FIND_NON_LINEAR_WHITESPACE));
|
assertEquals(23, buf.forEachByteDesc(0, 28, ByteProcessor.FIND_NON_LINEAR_WHITESPACE));
|
||||||
assertEquals(20, buf.forEachByteDesc(0, 24, ByteProcessor.FIND_NUL));
|
assertEquals(20, buf.forEachByteDesc(0, 24, ByteProcessor.FIND_NUL));
|
||||||
assertEquals(18, buf.forEachByteDesc(0, 21, ByteProcessor.FIND_NON_NUL));
|
assertEquals(18, buf.forEachByteDesc(0, 21, ByteProcessor.FIND_NON_NUL));
|
||||||
|
@ -116,7 +116,7 @@ public class HttpResponseDecoder extends HttpObjectDecoder {
|
|||||||
protected HttpMessage createMessage(String[] initialLine) {
|
protected HttpMessage createMessage(String[] initialLine) {
|
||||||
return new DefaultHttpResponse(
|
return new DefaultHttpResponse(
|
||||||
HttpVersion.valueOf(initialLine[0]),
|
HttpVersion.valueOf(initialLine[0]),
|
||||||
new HttpResponseStatus(Integer.parseInt(initialLine[1]), initialLine[2]), validateHeaders);
|
HttpResponseStatus.valueOf(Integer.parseInt(initialLine[1]), initialLine[2]), validateHeaders);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -15,13 +15,15 @@
|
|||||||
*/
|
*/
|
||||||
package io.netty.handler.codec.http;
|
package io.netty.handler.codec.http;
|
||||||
|
|
||||||
import static io.netty.handler.codec.http.HttpConstants.SP;
|
|
||||||
import io.netty.buffer.ByteBuf;
|
import io.netty.buffer.ByteBuf;
|
||||||
import io.netty.buffer.ByteBufUtil;
|
import io.netty.buffer.ByteBufUtil;
|
||||||
import io.netty.util.AsciiString;
|
import io.netty.util.AsciiString;
|
||||||
import io.netty.util.ByteProcessor;
|
|
||||||
import io.netty.util.CharsetUtil;
|
import io.netty.util.CharsetUtil;
|
||||||
|
|
||||||
|
import static io.netty.handler.codec.http.HttpConstants.SP;
|
||||||
|
import static io.netty.util.ByteProcessor.FIND_ASCII_SPACE;
|
||||||
|
import static java.lang.Integer.parseInt;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The response code and its description of HTTP or its derived protocols, such as
|
* The response code and its description of HTTP or its derived protocols, such as
|
||||||
* <a href="http://en.wikipedia.org/wiki/Real_Time_Streaming_Protocol">RTSP</a> and
|
* <a href="http://en.wikipedia.org/wiki/Real_Time_Streaming_Protocol">RTSP</a> and
|
||||||
@ -324,10 +326,15 @@ public class HttpResponseStatus implements Comparable<HttpResponseStatus> {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the {@link HttpResponseStatus} represented by the specified code.
|
* Returns the {@link HttpResponseStatus} represented by the specified code.
|
||||||
* If the specified code is a standard HTTP getStatus code, a cached instance
|
* If the specified code is a standard HTTP status code, a cached instance
|
||||||
* will be returned. Otherwise, a new instance will be returned.
|
* will be returned. Otherwise, a new instance will be returned.
|
||||||
*/
|
*/
|
||||||
public static HttpResponseStatus valueOf(int code) {
|
public static HttpResponseStatus valueOf(int code) {
|
||||||
|
HttpResponseStatus status = valueOf0(code);
|
||||||
|
return status != null ? status : new HttpResponseStatus(code);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static HttpResponseStatus valueOf0(int code) {
|
||||||
switch (code) {
|
switch (code) {
|
||||||
case 100:
|
case 100:
|
||||||
return CONTINUE;
|
return CONTINUE;
|
||||||
@ -442,8 +449,21 @@ public class HttpResponseStatus implements Comparable<HttpResponseStatus> {
|
|||||||
case 511:
|
case 511:
|
||||||
return NETWORK_AUTHENTICATION_REQUIRED;
|
return NETWORK_AUTHENTICATION_REQUIRED;
|
||||||
}
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
return new HttpResponseStatus(code);
|
/**
|
||||||
|
* Returns the {@link HttpResponseStatus} represented by the specified {@code code} and {@code reasonPhrase}.
|
||||||
|
* If the specified code is a standard HTTP status {@code code} and {@code reasonPhrase}, a cached instance
|
||||||
|
* will be returned. Otherwise, a new instance will be returned.
|
||||||
|
* @param code The response code value.
|
||||||
|
* @param reasonPhrase The response code reason phrase.
|
||||||
|
* @return the {@link HttpResponseStatus} represented by the specified {@code code} and {@code reasonPhrase}.
|
||||||
|
*/
|
||||||
|
public static HttpResponseStatus valueOf(int code, String reasonPhrase) {
|
||||||
|
HttpResponseStatus responseStatus = valueOf0(code);
|
||||||
|
return responseStatus != null && responseStatus.reasonPhrase().contentEquals(reasonPhrase) ? responseStatus :
|
||||||
|
new HttpResponseStatus(code, reasonPhrase);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -456,79 +476,25 @@ public class HttpResponseStatus implements Comparable<HttpResponseStatus> {
|
|||||||
* @throws IllegalArgumentException if the specified status line is malformed
|
* @throws IllegalArgumentException if the specified status line is malformed
|
||||||
*/
|
*/
|
||||||
public static HttpResponseStatus parseLine(CharSequence line) {
|
public static HttpResponseStatus parseLine(CharSequence line) {
|
||||||
String status = line.toString();
|
return (line instanceof AsciiString) ? parseLine((AsciiString) line) : parseLine(line.toString());
|
||||||
try {
|
|
||||||
int space = status.indexOf(' ');
|
|
||||||
if (space == -1) {
|
|
||||||
return valueOf(Integer.parseInt(status));
|
|
||||||
} else {
|
|
||||||
int code = Integer.parseInt(status.substring(0, space));
|
|
||||||
String reasonPhrase = status.substring(space + 1);
|
|
||||||
HttpResponseStatus responseStatus = valueOf(code);
|
|
||||||
if (responseStatus.reasonPhrase().contentEquals(reasonPhrase)) {
|
|
||||||
return responseStatus;
|
|
||||||
} else {
|
|
||||||
return new HttpResponseStatus(code, reasonPhrase);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} catch (Exception e) {
|
|
||||||
throw new IllegalArgumentException("malformed status line: " + status, e);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private static final class HttpStatusLineProcessor implements ByteProcessor {
|
|
||||||
private static final byte ASCII_SPACE = (byte) ' ';
|
|
||||||
private final AsciiString string;
|
|
||||||
private int i;
|
|
||||||
/**
|
/**
|
||||||
* 0 = New or havn't seen {@link #ASCII_SPACE}.
|
* Parses the specified HTTP status line into a {@link HttpResponseStatus}. The expected formats of the line are:
|
||||||
* 1 = Last byte was {@link #ASCII_SPACE}.
|
* <ul>
|
||||||
* 2 = Terminal State. Processed the byte after {@link #ASCII_SPACE}, and parsed the status line.
|
* <li>{@code statusCode} (e.g. 200)</li>
|
||||||
* 3 = Terminal State. There was no byte after {@link #ASCII_SPACE} but status has been parsed with what we saw.
|
* <li>{@code statusCode} {@code reasonPhrase} (e.g. 404 Not Found)</li>
|
||||||
|
* </ul>
|
||||||
|
*
|
||||||
|
* @throws IllegalArgumentException if the specified status line is malformed
|
||||||
*/
|
*/
|
||||||
private int state;
|
public static HttpResponseStatus parseLine(String line) {
|
||||||
private HttpResponseStatus status;
|
try {
|
||||||
|
int space = line.indexOf(' ');
|
||||||
public HttpStatusLineProcessor(AsciiString string) {
|
return space == -1 ? valueOf(parseInt(line)) :
|
||||||
this.string = string;
|
valueOf(parseInt(line.substring(0, space)), line.substring(space + 1));
|
||||||
}
|
} catch (Exception e) {
|
||||||
|
throw new IllegalArgumentException("malformed status line: " + line, e);
|
||||||
@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.parseInt(0, codeEnd);
|
|
||||||
status = valueOf(code);
|
|
||||||
if (codeEnd < string.length()) {
|
|
||||||
String actualReason = string.toString(codeEnd + 1, string.length());
|
|
||||||
if (!status.reasonPhrase().contentEquals(actualReason)) {
|
|
||||||
status = new HttpResponseStatus(code, actualReason);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public HttpResponseStatus status() {
|
|
||||||
if (state <= 1) {
|
|
||||||
parseStatus(string.length());
|
|
||||||
state = 3;
|
|
||||||
}
|
|
||||||
return status;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -543,13 +509,8 @@ public class HttpResponseStatus implements Comparable<HttpResponseStatus> {
|
|||||||
*/
|
*/
|
||||||
public static HttpResponseStatus parseLine(AsciiString line) {
|
public static HttpResponseStatus parseLine(AsciiString line) {
|
||||||
try {
|
try {
|
||||||
HttpStatusLineProcessor processor = new HttpStatusLineProcessor(line);
|
int space = line.forEachByte(FIND_ASCII_SPACE);
|
||||||
line.forEachByte(processor);
|
return space == -1 ? valueOf(line.parseInt()) : valueOf(line.parseInt(0, space), line.toString(space + 1));
|
||||||
HttpResponseStatus status = processor.status();
|
|
||||||
if (status == null) {
|
|
||||||
throw new IllegalArgumentException("unable to get status after parsing input");
|
|
||||||
}
|
|
||||||
return status;
|
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
throw new IllegalArgumentException("malformed status line: " + line, e);
|
throw new IllegalArgumentException("malformed status line: " + line, e);
|
||||||
}
|
}
|
||||||
@ -598,10 +559,11 @@ public class HttpResponseStatus implements Comparable<HttpResponseStatus> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
this.code = code;
|
this.code = code;
|
||||||
codeAsText = new AsciiString(Integer.toString(code));
|
String codeString = Integer.toString(code);
|
||||||
|
codeAsText = new AsciiString(codeString);
|
||||||
this.reasonPhrase = reasonPhrase;
|
this.reasonPhrase = reasonPhrase;
|
||||||
if (bytes) {
|
if (bytes) {
|
||||||
this.bytes = (code + " " + reasonPhrase).getBytes(CharsetUtil.US_ASCII);
|
this.bytes = (codeString + ' ' + reasonPhrase).getBytes(CharsetUtil.US_ASCII);
|
||||||
} else {
|
} else {
|
||||||
this.bytes = null;
|
this.bytes = null;
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,91 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2018 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.handler.codec.http;
|
||||||
|
|
||||||
|
import io.netty.util.AsciiString;
|
||||||
|
import org.junit.Test;
|
||||||
|
|
||||||
|
import static io.netty.handler.codec.http.HttpResponseStatus.parseLine;
|
||||||
|
import static org.junit.Assert.assertEquals;
|
||||||
|
import static org.junit.Assert.assertSame;
|
||||||
|
|
||||||
|
public class HttpResponseStatusTest {
|
||||||
|
@Test
|
||||||
|
public void parseLineStringJustCode() {
|
||||||
|
assertSame(HttpResponseStatus.OK, parseLine("200"));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void parseLineStringCodeAndPhrase() {
|
||||||
|
assertSame(HttpResponseStatus.OK, parseLine("200 OK"));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void parseLineStringCustomCode() {
|
||||||
|
HttpResponseStatus customStatus = parseLine("612");
|
||||||
|
assertEquals(612, customStatus.code());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void parseLineStringCustomCodeAndPhrase() {
|
||||||
|
HttpResponseStatus customStatus = parseLine("612 FOO");
|
||||||
|
assertEquals(612, customStatus.code());
|
||||||
|
assertEquals("FOO", customStatus.reasonPhrase());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test(expected = IllegalArgumentException.class)
|
||||||
|
public void parseLineStringMalformedCode() {
|
||||||
|
parseLine("200a");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test(expected = IllegalArgumentException.class)
|
||||||
|
public void parseLineStringMalformedCodeWithPhrase() {
|
||||||
|
parseLine("200a foo");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void parseLineAsciiStringJustCode() {
|
||||||
|
assertSame(HttpResponseStatus.OK, parseLine(new AsciiString("200")));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void parseLineAsciiStringCodeAndPhrase() {
|
||||||
|
assertSame(HttpResponseStatus.OK, parseLine(new AsciiString("200 OK")));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void parseLineAsciiStringCustomCode() {
|
||||||
|
HttpResponseStatus customStatus = parseLine(new AsciiString("612"));
|
||||||
|
assertEquals(612, customStatus.code());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void parseLineAsciiStringCustomCodeAndPhrase() {
|
||||||
|
HttpResponseStatus customStatus = parseLine(new AsciiString("612 FOO"));
|
||||||
|
assertEquals(612, customStatus.code());
|
||||||
|
assertEquals("FOO", customStatus.reasonPhrase());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test(expected = IllegalArgumentException.class)
|
||||||
|
public void parseLineAsciiStringMalformedCode() {
|
||||||
|
parseLine(new AsciiString("200a"));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test(expected = IllegalArgumentException.class)
|
||||||
|
public void parseLineAsciiStringMalformedCodeWithPhrase() {
|
||||||
|
parseLine(new AsciiString("200a foo"));
|
||||||
|
}
|
||||||
|
}
|
@ -44,6 +44,7 @@ import static io.netty.handler.codec.http.HttpHeaderNames.CONNECTION;
|
|||||||
import static io.netty.handler.codec.http.HttpHeaderNames.COOKIE;
|
import static io.netty.handler.codec.http.HttpHeaderNames.COOKIE;
|
||||||
import static io.netty.handler.codec.http.HttpHeaderNames.TE;
|
import static io.netty.handler.codec.http.HttpHeaderNames.TE;
|
||||||
import static io.netty.handler.codec.http.HttpHeaderValues.TRAILERS;
|
import static io.netty.handler.codec.http.HttpHeaderValues.TRAILERS;
|
||||||
|
import static io.netty.handler.codec.http.HttpResponseStatus.parseLine;
|
||||||
import static io.netty.handler.codec.http.HttpScheme.HTTP;
|
import static io.netty.handler.codec.http.HttpScheme.HTTP;
|
||||||
import static io.netty.handler.codec.http.HttpScheme.HTTPS;
|
import static io.netty.handler.codec.http.HttpScheme.HTTPS;
|
||||||
import static io.netty.handler.codec.http.HttpUtil.isAsteriskForm;
|
import static io.netty.handler.codec.http.HttpUtil.isAsteriskForm;
|
||||||
@ -183,7 +184,7 @@ public final class HttpConversionUtil {
|
|||||||
public static HttpResponseStatus parseStatus(CharSequence status) throws Http2Exception {
|
public static HttpResponseStatus parseStatus(CharSequence status) throws Http2Exception {
|
||||||
HttpResponseStatus result;
|
HttpResponseStatus result;
|
||||||
try {
|
try {
|
||||||
result = HttpResponseStatus.parseLine(status);
|
result = parseLine(status);
|
||||||
if (result == HttpResponseStatus.SWITCHING_PROTOCOLS) {
|
if (result == HttpResponseStatus.SWITCHING_PROTOCOLS) {
|
||||||
throw connectionError(PROTOCOL_ERROR, "Invalid HTTP/2 status code '%d'", result.code());
|
throw connectionError(PROTOCOL_ERROR, "Invalid HTTP/2 status code '%d'", result.code());
|
||||||
}
|
}
|
||||||
|
@ -14,6 +14,11 @@
|
|||||||
*/
|
*/
|
||||||
package io.netty.util;
|
package io.netty.util;
|
||||||
|
|
||||||
|
import static io.netty.util.ByteProcessorUtils.CARRIAGE_RETURN;
|
||||||
|
import static io.netty.util.ByteProcessorUtils.HTAB;
|
||||||
|
import static io.netty.util.ByteProcessorUtils.LINE_FEED;
|
||||||
|
import static io.netty.util.ByteProcessorUtils.SPACE;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Provides a mechanism to iterate over a collection of bytes.
|
* Provides a mechanism to iterate over a collection of bytes.
|
||||||
*/
|
*/
|
||||||
@ -63,22 +68,22 @@ public interface ByteProcessor {
|
|||||||
/**
|
/**
|
||||||
* Aborts on a {@code CR ('\r')}.
|
* Aborts on a {@code CR ('\r')}.
|
||||||
*/
|
*/
|
||||||
ByteProcessor FIND_CR = new IndexOfProcessor((byte) '\r');
|
ByteProcessor FIND_CR = new IndexOfProcessor(CARRIAGE_RETURN);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Aborts on a non-{@code CR ('\r')}.
|
* Aborts on a non-{@code CR ('\r')}.
|
||||||
*/
|
*/
|
||||||
ByteProcessor FIND_NON_CR = new IndexNotOfProcessor((byte) '\r');
|
ByteProcessor FIND_NON_CR = new IndexNotOfProcessor(CARRIAGE_RETURN);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Aborts on a {@code LF ('\n')}.
|
* Aborts on a {@code LF ('\n')}.
|
||||||
*/
|
*/
|
||||||
ByteProcessor FIND_LF = new IndexOfProcessor((byte) '\n');
|
ByteProcessor FIND_LF = new IndexOfProcessor(LINE_FEED);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Aborts on a non-{@code LF ('\n')}.
|
* Aborts on a non-{@code LF ('\n')}.
|
||||||
*/
|
*/
|
||||||
ByteProcessor FIND_NON_LF = new IndexNotOfProcessor((byte) '\n');
|
ByteProcessor FIND_NON_LF = new IndexNotOfProcessor(LINE_FEED);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Aborts on a semicolon {@code (';')}.
|
* Aborts on a semicolon {@code (';')}.
|
||||||
@ -90,13 +95,18 @@ public interface ByteProcessor {
|
|||||||
*/
|
*/
|
||||||
ByteProcessor FIND_COMMA = new IndexOfProcessor((byte) ',');
|
ByteProcessor FIND_COMMA = new IndexOfProcessor((byte) ',');
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Aborts on a ascii space character ({@code ' '}).
|
||||||
|
*/
|
||||||
|
ByteProcessor FIND_ASCII_SPACE = new IndexOfProcessor(SPACE);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Aborts on a {@code CR ('\r')} or a {@code LF ('\n')}.
|
* Aborts on a {@code CR ('\r')} or a {@code LF ('\n')}.
|
||||||
*/
|
*/
|
||||||
ByteProcessor FIND_CRLF = new ByteProcessor() {
|
ByteProcessor FIND_CRLF = new ByteProcessor() {
|
||||||
@Override
|
@Override
|
||||||
public boolean process(byte value) {
|
public boolean process(byte value) {
|
||||||
return value != '\r' && value != '\n';
|
return value != CARRIAGE_RETURN && value != LINE_FEED;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -106,7 +116,7 @@ public interface ByteProcessor {
|
|||||||
ByteProcessor FIND_NON_CRLF = new ByteProcessor() {
|
ByteProcessor FIND_NON_CRLF = new ByteProcessor() {
|
||||||
@Override
|
@Override
|
||||||
public boolean process(byte value) {
|
public boolean process(byte value) {
|
||||||
return value == '\r' || value == '\n';
|
return value == CARRIAGE_RETURN || value == LINE_FEED;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -116,7 +126,7 @@ public interface ByteProcessor {
|
|||||||
ByteProcessor FIND_LINEAR_WHITESPACE = new ByteProcessor() {
|
ByteProcessor FIND_LINEAR_WHITESPACE = new ByteProcessor() {
|
||||||
@Override
|
@Override
|
||||||
public boolean process(byte value) {
|
public boolean process(byte value) {
|
||||||
return value != ' ' && value != '\t';
|
return value != SPACE && value != HTAB;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -126,7 +136,7 @@ public interface ByteProcessor {
|
|||||||
ByteProcessor FIND_NON_LINEAR_WHITESPACE = new ByteProcessor() {
|
ByteProcessor FIND_NON_LINEAR_WHITESPACE = new ByteProcessor() {
|
||||||
@Override
|
@Override
|
||||||
public boolean process(byte value) {
|
public boolean process(byte value) {
|
||||||
return value == ' ' || value == '\t';
|
return value == SPACE || value == HTAB;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
25
common/src/main/java/io/netty/util/ByteProcessorUtils.java
Normal file
25
common/src/main/java/io/netty/util/ByteProcessorUtils.java
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2018 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;
|
||||||
|
|
||||||
|
final class ByteProcessorUtils {
|
||||||
|
static final byte SPACE = (byte) ' ';
|
||||||
|
static final byte HTAB = (byte) '\t';
|
||||||
|
static final byte CARRIAGE_RETURN = (byte) '\r';
|
||||||
|
static final byte LINE_FEED = (byte) '\n';
|
||||||
|
|
||||||
|
private ByteProcessorUtils() {
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user