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);
|
||||
}
|
||||
|
||||
@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
|
||||
public List<CharSequence> getAllUnconverted(CharSequence name) {
|
||||
if (name == null) {
|
||||
@ -501,6 +653,104 @@ public class DefaultTextHeaders implements TextHeaders {
|
||||
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
|
||||
public List<Map.Entry<String, String>> entries() {
|
||||
int cnt = 0;
|
||||
|
@ -67,11 +67,56 @@ public class EmptyTextHeaders implements TextHeaders {
|
||||
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
|
||||
public CharSequence getUnconverted(CharSequence name) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public CharSequence getUnconvertedAndRemove(CharSequence name) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<String> getAll(CharSequence name) {
|
||||
return Collections.emptyList();
|
||||
@ -82,6 +127,16 @@ public class EmptyTextHeaders implements TextHeaders {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<String> getAllAndRemove(CharSequence name) {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<CharSequence> getAllUnconvertedAndRemove(CharSequence name) {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<Entry<String, String>> entries() {
|
||||
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 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
|
||||
* 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);
|
||||
|
||||
/**
|
||||
* 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
|
||||
*
|
||||
@ -73,6 +170,22 @@ public interface TextHeaders extends Iterable<Map.Entry<String, String>> {
|
||||
*/
|
||||
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
|
||||
* 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