Skip to content

Instantly share code, notes, and snippets.

@buchgr
Created April 11, 2015 01:26
Show Gist options
  • Save buchgr/b2c2f5afe2c4b4ffbf96 to your computer and use it in GitHub Desktop.
Save buchgr/b2c2f5afe2c4b4ffbf96 to your computer and use it in GitHub Desktop.
package better.headers;
import io.netty.handler.codec.AsciiString;
import sun.misc.Unsafe;
import java.lang.reflect.Field;
public class Headers {
private static final Unsafe theUnsafe;
private static final int baseOffset;
static {
try {
Field unsafeField = Unsafe.class.getDeclaredField("theUnsafe");
unsafeField.setAccessible(true);
theUnsafe = (Unsafe) unsafeField.get(null);
baseOffset = theUnsafe.arrayBaseOffset(byte[].class);
} catch (Exception e) {
throw new RuntimeException(e);
}
}
private AsciiString[] names;
private int[] namesHashCode;
private AsciiString[] values;
private int idx;
public Headers(int numHeaders) {
names = new AsciiString[nextMultipleOfEight(numHeaders)];
namesHashCode = new int[nextMultipleOfEight(numHeaders)];
values = new AsciiString[nextMultipleOfEight(numHeaders)];
}
public void add(AsciiString name, AsciiString value) {
resizeIfNecessary();
names[idx] = name;
namesHashCode[idx] = name.hashCode();
values[idx] = value;
idx++;
}
public AsciiString get(AsciiString name) {
final int nameHashCode = name.hashCode();
final byte[] nameArray = name.array();
for (int i = 0; i < names.length; i += 8) {
if (compare(nameHashCode, nameArray, i)) return values[i];
if (compare(nameHashCode, nameArray, i+1)) return values[i+1];
if (compare(nameHashCode, nameArray, i+2)) return values[i+2];
if (compare(nameHashCode, nameArray, i+3)) return values[i+3];
if (compare(nameHashCode, nameArray, i+4)) return values[i+4];
if (compare(nameHashCode, nameArray, i+5)) return values[i+5];
if (compare(nameHashCode, nameArray, i+6)) return values[i+6];
if (compare(nameHashCode, nameArray, i+7)) return values[i+7];
}
return null;
}
private void resizeIfNecessary() {
if (idx == names.length) {
AsciiString[] newNames = new AsciiString[idx + 8];
System.arraycopy(names, 0, newNames, 0, idx);
AsciiString[] newValues = new AsciiString[idx + 8];
System.arraycopy(values, 0, newValues, 0, idx);
int[] newNamesHashCode = new int[idx + 8];
System.arraycopy(values, 0, newNamesHashCode, 0, idx);
names = newNames;
values = newValues;
namesHashCode = newNamesHashCode;
}
}
private boolean compare(final int nameHashCode, final byte[] bytes1, final int nameIdx) {
if (nameHashCode != namesHashCode[nameIdx]) return false;
final byte[] bytes2 = names[nameIdx].array();
int remainingLen = bytes1.length & 7;
for (int i = bytes1.length - 8; i >= remainingLen; i -= 8) {
final long word1 = theUnsafe.getLong(bytes1, baseOffset + (long) i);
final long word2 = theUnsafe.getLong(bytes2, baseOffset + (long) i);
if (word1 != word2) return false;
}
if (remainingLen >= 4) {
remainingLen -= 4;
final int word1 = theUnsafe.getInt(bytes1, baseOffset + (long) remainingLen);
final int word2 = theUnsafe.getInt(bytes2, baseOffset + (long) remainingLen);
if (word1 != word2) return false;
}
if (remainingLen == 3) return bytes1[2] == bytes2[2] && bytes1[1] == bytes2[1] && bytes1[0] == bytes2[0];
if (remainingLen == 2) return bytes1[1] == bytes2[1] && bytes1[0] == bytes2[0];
if (remainingLen == 1) return bytes1[0] == bytes2[0];
return true;
}
private static int nextMultipleOfEight(int num) {
return num + 7 & ~7;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment