asinger/tnetstringsj — Issue #4: A small modification to prevent unnecessary calculation
Author: mingodad
Created: 2012-01-19 14:33:54+00:00
State: open

With a small modification to the parse function we can skip recalculation of dataIndex and size on arrays and dictionaries.

-----

/** Internal parsing impl w/ an optimization if we want a String that prevents double copy */
private static Object parse(final byte[] msg, final int offset, final Charset charset, int out_i_size[]) {
if (msg == null || msg.length < 3)
throw new IllegalArgumentException("Nestring can't be null or < 3 length");
final int i = dataIndex(msg, offset);
final int size = parseSize(msg, offset, i - 1);
if (size > msg.length)
throw new IllegalArgumentException("Invalid tnetstring size. Can't be > msg size");
if(out_i_size != null){
out_i_size[0] = i;
out_i_size[1] = size;
}
final int typeIndex = i + size;
switch (msg[typeIndex]) {
case ',': return charset == null ? copyRange(msg, i, size) : parseString(msg, i, size, charset);
case '}': return parseDict(msg, i, size, charset);
case ']': return parseList(msg, i, size, charset);
case '#': return parseLong(msg, i, typeIndex);
case '^': return parseDouble(msg, i, typeIndex);
case '!': return msg[i] == 't' && msg[i + 1] == 'r' && msg[i + 2] == 'u' && msg[i + 3] == 'e';
case '~': if (size != 0) throw new IllegalArgumentException("Payload must be 0 length for null.");
return null;
default: throw new IllegalArgumentException(
"Invalid payload type: " + msg[typeIndex] + " at index: " + typeIndex);
}
}

private static Object parse(final byte[] msg, final int offset, final Charset charset) {
return parse(msg, offset, charset, null);
}
...

private static Map parseDict(final byte[] msg, final int dataIndex,
final int size, final Charset charset) {
if (size == 0) return Collections.emptyMap();
final Map map = new LinkedHashMap();
final int limit = dataIndex + size;
int[] out_i_size = new int[2];
Object okey, ovalue;
for (int keyIndex = dataIndex; keyIndex < limit; ) {
okey = parse(msg, keyIndex, charset, out_i_size);
final int valueIndex = out_i_size[0] + out_i_size[1] + 1;
ovalue = parse(msg, valueIndex, charset, out_i_size);
map.put(okey, ovalue);
keyIndex = out_i_size[0] + out_i_size[1] + 1;
}
return Collections.unmodifiableMap(map);
}

private static List