package io.vertx.core.http.impl.headers;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.ByteBufUtil;
import io.netty.handler.codec.http.HttpHeaders;
import io.netty.util.AsciiString;
import io.netty.util.CharsetUtil;
import io.netty.util.HashingStrategy;
import io.vertx.core.MultiMap;
import io.vertx.core.http.impl.HttpUtils;
import java.util.AbstractMap;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Set;
import java.util.TreeSet;
import java.util.function.Consumer;
import static io.netty.handler.codec.http.HttpConstants.*;
import static io.netty.util.AsciiString.*;
public final class extends HttpHeaders implements MultiMap {
@Override
public MultiMap (MultiMap headers) {
return set0(headers);
}
@Override
public MultiMap (Map<String, String> headers) {
return set0(headers.entrySet());
}
@Override
public int () {
return names().size();
}
private final VertxHttpHeaders.MapEntry[] = new VertxHttpHeaders.MapEntry[16];
private final VertxHttpHeaders.MapEntry = new VertxHttpHeaders.MapEntry();
public () {
head.before = head.after = head;
}
@Override
public VertxHttpHeaders (CharSequence name, CharSequence value) {
int h = AsciiString.hashCode(name);
int i = h & 0x0000000F;
add0(h, i, name, value);
return this;
}
@Override
public VertxHttpHeaders (CharSequence name, Object value) {
return add(name, (CharSequence)value);
}
@Override
public HttpHeaders (String name, Object value) {
return add((CharSequence) name, (CharSequence) value);
}
@Override
public VertxHttpHeaders (String name, String strVal) {
return add((CharSequence) name, strVal);
}
@Override
public VertxHttpHeaders (CharSequence name, Iterable values) {
int h = AsciiString.hashCode(name);
int i = h & 0x0000000F;
for (Object vstr: values) {
add0(h, i, name, (String) vstr);
}
return this;
}
@Override
public VertxHttpHeaders (String name, Iterable values) {
return add((CharSequence) name, values);
}
@Override
public MultiMap (MultiMap headers) {
return addAll(headers.entries());
}
@Override
public MultiMap (Map<String, String> map) {
return addAll(map.entrySet());
}
private MultiMap (Iterable<Map.Entry<String, String>> headers) {
for (Map.Entry<String, String> entry: headers) {
add(entry.getKey(), entry.getValue());
}
return this;
}
@Override
public VertxHttpHeaders (CharSequence name) {
Objects.requireNonNull(name, "name");
int h = AsciiString.hashCode(name);
int i = h & 0x0000000F;
remove0(h, i, name);
return this;
}
@Override
public VertxHttpHeaders (final String name) {
return remove((CharSequence) name);
}
@Override
public VertxHttpHeaders (CharSequence name, CharSequence value) {
return set0(name, value);
}
@Override
public VertxHttpHeaders (String name, String value) {
return set((CharSequence)name, value);
}
@Override
public VertxHttpHeaders (String name, Object value) {
return set((CharSequence)name, (CharSequence) value);
}
@Override
public VertxHttpHeaders (CharSequence name, Object value) {
return set(name, (CharSequence)value);
}
@Override
public VertxHttpHeaders (CharSequence name, Iterable values) {
Objects.requireNonNull(values, "values");
int h = AsciiString.hashCode(name);
int i = h & 0x0000000F;
remove0(h, i, name);
for (Object v: values) {
if (v == null) {
break;
}
add0(h, i, name, (CharSequence) v);
}
return this;
}
@Override
public VertxHttpHeaders (String name, Iterable values) {
return set((CharSequence) name, values);
}
@Override
public boolean (CharSequence name, CharSequence value, boolean ignoreCase) {
int h = AsciiString.hashCode(name);
int i = h & 0x0000000F;
VertxHttpHeaders.MapEntry e = entries[i];
HashingStrategy<CharSequence> strategy = ignoreCase ? CASE_INSENSITIVE_HASHER : CASE_SENSITIVE_HASHER;
while (e != null) {
CharSequence key = e.key;
if (e.hash == h && (name == key || AsciiString.contentEqualsIgnoreCase(name, key))) {
if (strategy.equals(value, e.getValue())) {
return true;
}
}
e = e.next;
}
return false;
}
@Override
public boolean (String name, String value, boolean ignoreCase) {
return contains((CharSequence) name, value, ignoreCase);
}
@Override
public boolean (CharSequence name) {
return get0(name) != null;
}
@Override
public boolean (String name) {
return contains((CharSequence) name);
}
@Override
public String (CharSequence name) {
Objects.requireNonNull(name, "name");
CharSequence ret = get0(name);
return ret != null ? ret.toString() : null;
}
@Override
public String (String name) {
return get((CharSequence) name);
}
@Override
public List<String> (CharSequence name) {
Objects.requireNonNull(name, "name");
LinkedList<String> values = new LinkedList<>();
int h = AsciiString.hashCode(name);
int i = h & 0x0000000F;
VertxHttpHeaders.MapEntry e = entries[i];
while (e != null) {
CharSequence key = e.key;
if (e.hash == h && (name == key || AsciiString.contentEqualsIgnoreCase(name, key))) {
values.addFirst(e.getValue().toString());
}
e = e.next;
}
return values;
}
@Override
public List<String> (String name) {
return getAll((CharSequence) name);
}
@Override
public void (Consumer<? super Map.Entry<String, String>> action) {
VertxHttpHeaders.MapEntry e = head.after;
while (e != head) {
action.accept(new AbstractMap.SimpleEntry<>(e.key.toString(), e.value.toString()));
e = e.after;
}
}
@Override
public List<Map.Entry<String, String>> () {
List<Map.Entry<String, String>> all = new ArrayList<>(size());
VertxHttpHeaders.MapEntry e = head.after;
while (e != head) {
final MapEntry f = e;
all.add(new Map.Entry<String, String>() {
@Override
public String () {
return f.key.toString();
}
@Override
public String () {
return f.value.toString();
}
@Override
public String (String value) {
return f.setValue(value).toString();
}
@Override
public String () {
return getKey() + ": " + getValue();
}
});
e = e.after;
}
return all;
}
@Override
public Iterator<Map.Entry<String, String>> () {
return entries().iterator();
}
@Override
public boolean () {
return head == head.after;
}
@Override
public Set<String> () {
Set<String> names = new TreeSet<>(String.CASE_INSENSITIVE_ORDER);
VertxHttpHeaders.MapEntry e = head.after;
while (e != head) {
names.add(e.getKey().toString());
e = e.after;
}
return names;
}
@Override
public VertxHttpHeaders () {
for (int i = 0; i < entries.length; i ++) {
entries[i] = null;
}
head.before = head.after = head;
return this;
}
public String () {
StringBuilder sb = new StringBuilder();
for (Map.Entry<String, String> entry: this) {
sb.append(entry).append('\n');
}
return sb.toString();
}
@Override
public Integer (CharSequence name) {
throw new UnsupportedOperationException();
}
@Override
public int (CharSequence name, int defaultValue) {
throw new UnsupportedOperationException();
}
@Override
public Short (CharSequence name) {
throw new UnsupportedOperationException();
}
@Override
public short (CharSequence name, short defaultValue) {
throw new UnsupportedOperationException();
}
@Override
public Long (CharSequence name) {
throw new UnsupportedOperationException();
}
@Override
public long (CharSequence name, long defaultValue) {
throw new UnsupportedOperationException();
}
@Override
public Iterator<Map.Entry<CharSequence, CharSequence>> () {
return new Iterator<Map.Entry<CharSequence, CharSequence>>() {
VertxHttpHeaders.MapEntry = head.after;
@Override
public boolean () {
return current != head;
}
@Override
public Map.Entry<CharSequence, CharSequence> () {
Map.Entry<CharSequence, CharSequence> next = current;
current = current.after;
return next;
}
};
}
@Override
public HttpHeaders (CharSequence name, int value) {
throw new UnsupportedOperationException();
}
@Override
public HttpHeaders (CharSequence name, short value) {
throw new UnsupportedOperationException();
}
@Override
public HttpHeaders (CharSequence name, int value) {
return set(name, Integer.toString(value));
}
@Override
public HttpHeaders (CharSequence name, short value) {
throw new UnsupportedOperationException();
}
public void (ByteBuf buf) {
VertxHttpHeaders.MapEntry current = head.after;
while (current != head) {
encoderHeader(current.key, current.value, buf);
current = current.after;
}
}
private static final int COLON_AND_SPACE_SHORT = (COLON << 8) | SP;
static final int = (CR << 8) | LF;
static void (CharSequence name, CharSequence value, ByteBuf buf) {
final int nameLen = name.length();
final int valueLen = value.length();
final int entryLen = nameLen + valueLen + 4;
buf.ensureWritable(entryLen);
int offset = buf.writerIndex();
writeAscii(buf, offset, name);
offset += nameLen;
ByteBufUtil.setShortBE(buf, offset, COLON_AND_SPACE_SHORT);
offset += 2;
writeAscii(buf, offset, value);
offset += valueLen;
ByteBufUtil.setShortBE(buf, offset, CRLF_SHORT);
offset += 2;
buf.writerIndex(offset);
}
private static void (ByteBuf buf, int offset, CharSequence value) {
if (value instanceof AsciiString) {
ByteBufUtil.copy((AsciiString) value, 0, buf, offset, value.length());
} else {
buf.setCharSequence(offset, value, CharsetUtil.US_ASCII);
}
}
private static final class implements Map.Entry<CharSequence, CharSequence> {
final int ;
final CharSequence ;
CharSequence ;
VertxHttpHeaders.MapEntry ;
VertxHttpHeaders.MapEntry , ;
() {
this.hash = -1;
this.key = null;
this.value = null;
}
(int hash, CharSequence key, CharSequence value) {
this.hash = hash;
this.key = key;
this.value = value;
}
void () {
before.after = after;
after.before = before;
}
void (VertxHttpHeaders.MapEntry e) {
after = e;
before = e.before;
before.after = this;
after.before = this;
}
@Override
public CharSequence () {
return key;
}
@Override
public CharSequence () {
return value;
}
@Override
public CharSequence (CharSequence value) {
Objects.requireNonNull(value, "value");
if (!io.vertx.core.http.HttpHeaders.DISABLE_HTTP_HEADERS_VALIDATION) {
HttpUtils.validateHeaderValue(value);
}
CharSequence oldValue = this.value;
this.value = value;
return oldValue;
}
@Override
public String () {
return getKey() + ": " + getValue();
}
}
private void (int h, int i, CharSequence name) {
VertxHttpHeaders.MapEntry e = entries[i];
if (e == null) {
return;
}
for (;;) {
CharSequence key = e.key;
if (e.hash == h && (name == key || AsciiString.contentEqualsIgnoreCase(name, key))) {
e.remove();
VertxHttpHeaders.MapEntry next = e.next;
if (next != null) {
entries[i] = next;
e = next;
} else {
entries[i] = null;
return;
}
} else {
break;
}
}
for (;;) {
VertxHttpHeaders.MapEntry next = e.next;
if (next == null) {
break;
}
CharSequence key = next.key;
if (next.hash == h && (name == key || AsciiString.contentEqualsIgnoreCase(name, key))) {
e.next = next.next;
next.remove();
} else {
e = next;
}
}
}
private void (int h, int i, final CharSequence name, final CharSequence value) {
if (!io.vertx.core.http.HttpHeaders.DISABLE_HTTP_HEADERS_VALIDATION) {
HttpUtils.validateHeader(name, value);
}
VertxHttpHeaders.MapEntry e = entries[i];
VertxHttpHeaders.MapEntry newEntry;
entries[i] = newEntry = new VertxHttpHeaders.MapEntry(h, name, value);
newEntry.next = e;
newEntry.addBefore(head);
}
private VertxHttpHeaders (final CharSequence name, final CharSequence strVal) {
int h = AsciiString.hashCode(name);
int i = h & 0x0000000F;
remove0(h, i, name);
if (strVal != null) {
add0(h, i, name, strVal);
}
return this;
}
private CharSequence (CharSequence name) {
int h = AsciiString.hashCode(name);
int i = h & 0x0000000F;
VertxHttpHeaders.MapEntry e = entries[i];
CharSequence value = null;
while (e != null) {
CharSequence key = e.key;
if (e.hash == h && (name == key || AsciiString.contentEqualsIgnoreCase(name, key))) {
value = e.getValue();
}
e = e.next;
}
return value;
}
private MultiMap (Iterable<Map.Entry<String, String>> map) {
clear();
for (Map.Entry<String, String> entry: map) {
add(entry.getKey(), entry.getValue());
}
return this;
}
}