Add TextHeaders.getAndRemove(...) and its variants
Related issue: #2649 and #2745 Motivation: At the moment there is no way to get and remove a header with one call. This means you need to search the headers two times. We should add getAndRemove(...) to allow doing so with one call. Modifications: Add getAndRemove(...) and getUnconvertedAndRemove(...) and their variants Result: More efficient API
This commit is contained in:
parent
286b89933c
commit
2d36caa9f6
@ -459,6 +459,158 @@ public class DefaultTextHeaders implements TextHeaders {
|
|||||||
return HttpHeaderDateFormat.get().parse(v.toString(), defaultValue);
|
return HttpHeaderDateFormat.get().parse(v.toString(), defaultValue);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public CharSequence getUnconvertedAndRemove(CharSequence name) {
|
||||||
|
if (name == null) {
|
||||||
|
throw new NullPointerException("name");
|
||||||
|
}
|
||||||
|
int h = hashCode(name);
|
||||||
|
int i = index(h);
|
||||||
|
HeaderEntry e = entries[i];
|
||||||
|
if (e == null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
CharSequence value = null;
|
||||||
|
for (;;) {
|
||||||
|
if (e.hash == h && nameEquals(e.name, name)) {
|
||||||
|
value = e.value;
|
||||||
|
e.remove();
|
||||||
|
HeaderEntry next = e.next;
|
||||||
|
if (next != null) {
|
||||||
|
entries[i] = next;
|
||||||
|
e = next;
|
||||||
|
} else {
|
||||||
|
entries[i] = null;
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (;;) {
|
||||||
|
HeaderEntry next = e.next;
|
||||||
|
if (next == null) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (next.hash == h && nameEquals(next.name, name)) {
|
||||||
|
value = next.value;
|
||||||
|
e.next = next.next;
|
||||||
|
next.remove();
|
||||||
|
} else {
|
||||||
|
e = next;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (value != null) {
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getAndRemove(CharSequence name) {
|
||||||
|
CharSequence v = getUnconvertedAndRemove(name);
|
||||||
|
if (v == null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
return v.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getAndRemove(CharSequence name, String defaultValue) {
|
||||||
|
CharSequence v = getUnconvertedAndRemove(name);
|
||||||
|
if (v == null) {
|
||||||
|
return defaultValue;
|
||||||
|
}
|
||||||
|
return v.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getIntAndRemove(CharSequence name) {
|
||||||
|
CharSequence v = getUnconvertedAndRemove(name);
|
||||||
|
if (v == null) {
|
||||||
|
throw new NoSuchElementException(String.valueOf(name));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (v instanceof AsciiString) {
|
||||||
|
return ((AsciiString) v).parseInt();
|
||||||
|
} else {
|
||||||
|
return Integer.parseInt(v.toString());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getIntAndRemove(CharSequence name, int defaultValue) {
|
||||||
|
CharSequence v = getUnconvertedAndRemove(name);
|
||||||
|
if (v == null) {
|
||||||
|
return defaultValue;
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
if (v instanceof AsciiString) {
|
||||||
|
return ((AsciiString) v).parseInt();
|
||||||
|
} else {
|
||||||
|
return Integer.parseInt(v.toString());
|
||||||
|
}
|
||||||
|
} catch (NumberFormatException ignored) {
|
||||||
|
return defaultValue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public long getLongAndRemove(CharSequence name) {
|
||||||
|
CharSequence v = getUnconvertedAndRemove(name);
|
||||||
|
if (v == null) {
|
||||||
|
throw new NoSuchElementException(String.valueOf(name));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (v instanceof AsciiString) {
|
||||||
|
return ((AsciiString) v).parseLong();
|
||||||
|
} else {
|
||||||
|
return Long.parseLong(v.toString());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public long getLongAndRemove(CharSequence name, long defaultValue) {
|
||||||
|
CharSequence v = getUnconvertedAndRemove(name);
|
||||||
|
if (v == null) {
|
||||||
|
return defaultValue;
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
if (v instanceof AsciiString) {
|
||||||
|
return ((AsciiString) v).parseLong();
|
||||||
|
} else {
|
||||||
|
return Long.parseLong(v.toString());
|
||||||
|
}
|
||||||
|
} catch (NumberFormatException ignored) {
|
||||||
|
return defaultValue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public long getTimeMillisAndRemove(CharSequence name) {
|
||||||
|
CharSequence v = getUnconvertedAndRemove(name);
|
||||||
|
if (v == null) {
|
||||||
|
throw new NoSuchElementException(String.valueOf(name));
|
||||||
|
}
|
||||||
|
|
||||||
|
return HttpHeaderDateFormat.get().parse(v.toString());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public long getTimeMillisAndRemove(CharSequence name, long defaultValue) {
|
||||||
|
CharSequence v = getUnconvertedAndRemove(name);
|
||||||
|
if (v == null) {
|
||||||
|
return defaultValue;
|
||||||
|
}
|
||||||
|
|
||||||
|
return HttpHeaderDateFormat.get().parse(v.toString(), defaultValue);
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public List<CharSequence> getAllUnconverted(CharSequence name) {
|
public List<CharSequence> getAllUnconverted(CharSequence name) {
|
||||||
if (name == null) {
|
if (name == null) {
|
||||||
@ -501,6 +653,104 @@ public class DefaultTextHeaders implements TextHeaders {
|
|||||||
return values;
|
return values;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<String> getAllAndRemove(CharSequence name) {
|
||||||
|
if (name == null) {
|
||||||
|
throw new NullPointerException("name");
|
||||||
|
}
|
||||||
|
int h = hashCode(name);
|
||||||
|
int i = index(h);
|
||||||
|
HeaderEntry e = entries[i];
|
||||||
|
if (e == null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
List<String> values = new ArrayList<String>(4);
|
||||||
|
for (;;) {
|
||||||
|
if (e.hash == h && nameEquals(e.name, name)) {
|
||||||
|
values.add(e.getValue().toString());
|
||||||
|
e.remove();
|
||||||
|
HeaderEntry next = e.next;
|
||||||
|
if (next != null) {
|
||||||
|
entries[i] = next;
|
||||||
|
e = next;
|
||||||
|
} else {
|
||||||
|
entries[i] = null;
|
||||||
|
Collections.reverse(values);
|
||||||
|
return values;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (;;) {
|
||||||
|
HeaderEntry next = e.next;
|
||||||
|
if (next == null) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (next.hash == h && nameEquals(next.name, name)) {
|
||||||
|
values.add(next.getValue().toString());
|
||||||
|
e.next = next.next;
|
||||||
|
next.remove();
|
||||||
|
} else {
|
||||||
|
e = next;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Collections.reverse(values);
|
||||||
|
return values;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<CharSequence> getAllUnconvertedAndRemove(CharSequence name) {
|
||||||
|
if (name == null) {
|
||||||
|
throw new NullPointerException("name");
|
||||||
|
}
|
||||||
|
int h = hashCode(name);
|
||||||
|
int i = index(h);
|
||||||
|
HeaderEntry e = entries[i];
|
||||||
|
if (e == null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
List<CharSequence> values = new ArrayList<CharSequence>(4);
|
||||||
|
for (;;) {
|
||||||
|
if (e.hash == h && nameEquals(e.name, name)) {
|
||||||
|
values.add(e.getValue());
|
||||||
|
e.remove();
|
||||||
|
HeaderEntry next = e.next;
|
||||||
|
if (next != null) {
|
||||||
|
entries[i] = next;
|
||||||
|
e = next;
|
||||||
|
} else {
|
||||||
|
entries[i] = null;
|
||||||
|
Collections.reverse(values);
|
||||||
|
return values;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (;;) {
|
||||||
|
HeaderEntry next = e.next;
|
||||||
|
if (next == null) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (next.hash == h && nameEquals(next.name, name)) {
|
||||||
|
values.add(next.getValue());
|
||||||
|
e.next = next.next;
|
||||||
|
next.remove();
|
||||||
|
} else {
|
||||||
|
e = next;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Collections.reverse(values);
|
||||||
|
return values;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public List<Map.Entry<String, String>> entries() {
|
public List<Map.Entry<String, String>> entries() {
|
||||||
int cnt = 0;
|
int cnt = 0;
|
||||||
|
@ -67,11 +67,56 @@ public class EmptyTextHeaders implements TextHeaders {
|
|||||||
return defaultValue;
|
return defaultValue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getAndRemove(CharSequence name) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getAndRemove(CharSequence name, String defaultValue) {
|
||||||
|
return defaultValue;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getIntAndRemove(CharSequence name) {
|
||||||
|
throw new NoSuchElementException(String.valueOf(name));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getIntAndRemove(CharSequence name, int defaultValue) {
|
||||||
|
return defaultValue;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public long getLongAndRemove(CharSequence name) {
|
||||||
|
throw new NoSuchElementException(String.valueOf(name));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public long getLongAndRemove(CharSequence name, long defaultValue) {
|
||||||
|
return defaultValue;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public long getTimeMillisAndRemove(CharSequence name) {
|
||||||
|
throw new NoSuchElementException(String.valueOf(name));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public long getTimeMillisAndRemove(CharSequence name, long defaultValue) {
|
||||||
|
return defaultValue;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public CharSequence getUnconverted(CharSequence name) {
|
public CharSequence getUnconverted(CharSequence name) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public CharSequence getUnconvertedAndRemove(CharSequence name) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public List<String> getAll(CharSequence name) {
|
public List<String> getAll(CharSequence name) {
|
||||||
return Collections.emptyList();
|
return Collections.emptyList();
|
||||||
@ -82,6 +127,16 @@ public class EmptyTextHeaders implements TextHeaders {
|
|||||||
return Collections.emptyList();
|
return Collections.emptyList();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<String> getAllAndRemove(CharSequence name) {
|
||||||
|
return Collections.emptyList();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<CharSequence> getAllUnconvertedAndRemove(CharSequence name) {
|
||||||
|
return Collections.emptyList();
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public List<Entry<String, String>> entries() {
|
public List<Entry<String, String>> entries() {
|
||||||
return Collections.emptyList();
|
return Collections.emptyList();
|
||||||
|
@ -48,6 +48,94 @@ public interface TextHeaders extends Iterable<Map.Entry<String, String>> {
|
|||||||
long getTimeMillis(CharSequence name);
|
long getTimeMillis(CharSequence name);
|
||||||
long getTimeMillis(CharSequence name, long defaultValue);
|
long getTimeMillis(CharSequence name, long defaultValue);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns and Removes the value of a header with the specified name. If there are
|
||||||
|
* more than one values for the specified name, the first value is returned.
|
||||||
|
*
|
||||||
|
* @param name The name of the header to search
|
||||||
|
* @return The first header value or {@code null} if there is no such header
|
||||||
|
*/
|
||||||
|
String getAndRemove(CharSequence name);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns and Removes the value of a header with the specified name. If there are
|
||||||
|
* more than one values for the specified name, the first value is returned.
|
||||||
|
*
|
||||||
|
* @param name The name of the header to search
|
||||||
|
* @param defaultValue default value
|
||||||
|
* @return The first header value or {@code defaultValue} if there is no such header
|
||||||
|
*/
|
||||||
|
String getAndRemove(CharSequence name, String defaultValue);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns and Removes the integer value of a header with the specified name. If there are
|
||||||
|
* more than one values for the specified name, the first value is returned.
|
||||||
|
*
|
||||||
|
* @param name The name of the header to search
|
||||||
|
* @return The first header value
|
||||||
|
* @throws java.util.NoSuchElementException
|
||||||
|
* if no such header
|
||||||
|
* @throws NumberFormatException
|
||||||
|
* if the value of header is not number
|
||||||
|
*/
|
||||||
|
int getIntAndRemove(CharSequence name);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns and Removes the integer value of a header with the specified name. If there are more than one values for
|
||||||
|
* the specified name, the first value is returned.
|
||||||
|
*
|
||||||
|
* @param name The name of the header to search
|
||||||
|
* @param defaultValue default value
|
||||||
|
* @return The first header value or {@code defaultValue} if there is no such header or the value of header is not
|
||||||
|
* number
|
||||||
|
*/
|
||||||
|
int getIntAndRemove(CharSequence name, int defaultValue);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns and Removes the long value of a header with the specified name. If there are
|
||||||
|
* more than one values for the specified name, the first value is returned.
|
||||||
|
*
|
||||||
|
* @param name The name of the header to search
|
||||||
|
* @return The first header value
|
||||||
|
* @throws java.util.NoSuchElementException
|
||||||
|
* if no such header
|
||||||
|
* @throws NumberFormatException
|
||||||
|
* if the value of header is not number
|
||||||
|
*/
|
||||||
|
long getLongAndRemove(CharSequence name);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns and Removes the long value of a header with the specified name. If there are more than one values for
|
||||||
|
* the specified name, the first value is returned.
|
||||||
|
*
|
||||||
|
* @param name The name of the header to search
|
||||||
|
* @param defaultValue default value
|
||||||
|
* @return The first header value or {@code defaultValue} if there is no such header or the value of header is not
|
||||||
|
* number
|
||||||
|
*/
|
||||||
|
long getLongAndRemove(CharSequence name, long defaultValue);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns and Removes the millisecond value of a header with the specified name. If there are
|
||||||
|
* more than one values for the specified name, the first value is returned.
|
||||||
|
*
|
||||||
|
* @param name The name of the header to search
|
||||||
|
* @return The first header value
|
||||||
|
* @throws java.util.NoSuchElementException
|
||||||
|
* if no such header
|
||||||
|
*/
|
||||||
|
long getTimeMillisAndRemove(CharSequence name);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns and Removes the millisecond value of a header with the specified name. If there are more than one values
|
||||||
|
* for the specified name, the first value is returned.
|
||||||
|
*
|
||||||
|
* @param name The name of the header to search
|
||||||
|
* @param defaultValue default value
|
||||||
|
* @return The first header value or {@code defaultValue} if there is no such header
|
||||||
|
*/
|
||||||
|
long getTimeMillisAndRemove(CharSequence name, long defaultValue);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the value of a header with the specified name. If there are
|
* Returns the value of a header with the specified name. If there are
|
||||||
* more than one values for the specified name, the first value is returned.
|
* more than one values for the specified name, the first value is returned.
|
||||||
@ -57,6 +145,15 @@ public interface TextHeaders extends Iterable<Map.Entry<String, String>> {
|
|||||||
*/
|
*/
|
||||||
CharSequence getUnconverted(CharSequence name);
|
CharSequence getUnconverted(CharSequence name);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns and Removes the value of a header with the specified name. If there are
|
||||||
|
* more than one values for the specified name, the first value is returned.
|
||||||
|
*
|
||||||
|
* @param name The name of the header to search
|
||||||
|
* @return The first header value or {@code null} if there is no such header
|
||||||
|
*/
|
||||||
|
CharSequence getUnconvertedAndRemove(CharSequence name);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the values of headers with the specified name
|
* Returns the values of headers with the specified name
|
||||||
*
|
*
|
||||||
@ -73,6 +170,22 @@ public interface TextHeaders extends Iterable<Map.Entry<String, String>> {
|
|||||||
*/
|
*/
|
||||||
List<CharSequence> getAllUnconverted(CharSequence name);
|
List<CharSequence> getAllUnconverted(CharSequence name);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns and Removes the values of headers with the specified name
|
||||||
|
*
|
||||||
|
* @param name The name of the headers to search
|
||||||
|
* @return A {@link List} of header values which will be empty if no values are found
|
||||||
|
*/
|
||||||
|
List<String> getAllAndRemove(CharSequence name);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns and Removes the values of headers with the specified name
|
||||||
|
*
|
||||||
|
* @param name The name of the headers to search
|
||||||
|
* @return A {@link List} of header values which will be empty if no values are found
|
||||||
|
*/
|
||||||
|
List<CharSequence> getAllUnconvertedAndRemove(CharSequence name);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns a new {@link List} that contains all headers in this object. Note that modifying the
|
* Returns a new {@link List} that contains all headers in this object. Note that modifying the
|
||||||
* returned {@link List} will not affect the state of this object. If you intend to enumerate over the header
|
* returned {@link List} will not affect the state of this object. If you intend to enumerate over the header
|
||||||
|
Loading…
Reference in New Issue
Block a user