diff options
author | Jon Bratseth <bratseth@yahoo-inc.com> | 2016-06-15 23:09:44 +0200 |
---|---|---|
committer | Jon Bratseth <bratseth@yahoo-inc.com> | 2016-06-15 23:09:44 +0200 |
commit | 72231250ed81e10d66bfe70701e64fa5fe50f712 (patch) | |
tree | 2728bba1131a6f6e5bdf95afec7d7ff9358dac50 /vespajlib/src/main/java/com/yahoo/slime/BinaryEncoder.java |
Publish
Diffstat (limited to 'vespajlib/src/main/java/com/yahoo/slime/BinaryEncoder.java')
-rw-r--r-- | vespajlib/src/main/java/com/yahoo/slime/BinaryEncoder.java | 144 |
1 files changed, 144 insertions, 0 deletions
diff --git a/vespajlib/src/main/java/com/yahoo/slime/BinaryEncoder.java b/vespajlib/src/main/java/com/yahoo/slime/BinaryEncoder.java new file mode 100644 index 00000000000..daa926ec45b --- /dev/null +++ b/vespajlib/src/main/java/com/yahoo/slime/BinaryEncoder.java @@ -0,0 +1,144 @@ +// Copyright 2016 Yahoo Inc. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. +package com.yahoo.slime; + +import static com.yahoo.slime.BinaryFormat.*; + +final class BinaryEncoder implements +ArrayTraverser, ObjectSymbolTraverser +{ + BufferedOutput out; + + public BinaryEncoder(int capacity) { + out = new BufferedOutput(capacity); + } + + public BinaryEncoder() { + out = new BufferedOutput(); + } + + public byte[] encode(Slime slime) { + out.reset(); + encodeSymbolTable(slime); + encodeValue(slime.get()); + return out.toArray(); + } + + void encode_cmpr_long(long value) { + byte next = (byte)(value & 0x7f); + value >>>= 7; // unsigned shift + while (value != 0) { + next |= 0x80; + out.put(next); + next = (byte)(value & 0x7f); + value >>>= 7; + } + out.put(next); + } + + void write_type_and_size(int type, long size) { + if (size <= 30) { + out.put(encode_type_and_meta(type, (int)(size + 1))); + } else { + out.put(encode_type_and_meta(type, 0)); + encode_cmpr_long(size); + } + } + + void write_type_and_bytes_le(int type, long bits) { + int pos = out.position(); + byte val = 0; + out.put(val); + while (bits != 0) { + val = (byte)(bits & 0xff); + bits >>>= 8; + out.put(val); + } + val = encode_type_and_meta(type, out.position() - pos - 1); + out.absolutePut(pos, val); + } + + void write_type_and_bytes_be(int type, long bits) { + int pos = out.position(); + byte val = 0; + out.put(val); + while (bits != 0) { + val = (byte)(bits >> 56); + bits <<= 8; + out.put(val); + } + val = encode_type_and_meta(type, out.position() - pos - 1); + out.absolutePut(pos, val); + } + + void encodeNIX() { + out.put(Type.NIX.ID); + } + + void encodeBOOL(boolean value) { + out.put(encode_type_and_meta(Type.BOOL.ID, value ? 1 : 0)); + } + + void encodeLONG(long value) { + write_type_and_bytes_le(Type.LONG.ID, encode_zigzag(value)); + } + + void encodeDOUBLE(double value) { + write_type_and_bytes_be(Type.DOUBLE.ID, encode_double(value)); + } + + void encodeSTRING(byte[] value) { + write_type_and_size(Type.STRING.ID, value.length); + out.put(value); + } + + void encodeDATA(byte[] value) { + write_type_and_size(Type.DATA.ID, value.length); + out.put(value); + } + + void encodeARRAY(Inspector inspector) { + write_type_and_size(Type.ARRAY.ID, inspector.children()); + ArrayTraverser at = this; + inspector.traverse(at); + } + + void encodeOBJECT(Inspector inspector) { + write_type_and_size(Type.OBJECT.ID, inspector.children()); + ObjectSymbolTraverser ot = this; + inspector.traverse(ot); + } + + void encodeValue(Inspector inspector) { + switch(inspector.type()) { + case NIX: encodeNIX(); return; + case BOOL: encodeBOOL(inspector.asBool()); return; + case LONG: encodeLONG(inspector.asLong()); return; + case DOUBLE: encodeDOUBLE(inspector.asDouble()); return; + case STRING: encodeSTRING(inspector.asUtf8()); return; + case DATA: encodeDATA(inspector.asData()); return; + case ARRAY: encodeARRAY(inspector); return; + case OBJECT: encodeOBJECT(inspector); return; + } + assert false : "Should not be reached"; + } + + void encodeSymbolTable(Slime slime) { + int numSymbols = slime.symbols(); + encode_cmpr_long(numSymbols); + for (int i = 0 ; i < numSymbols; ++i) { + String name = slime.inspect(i); + byte[] bytes = Utf8Codec.encode(name); + encode_cmpr_long(bytes.length); + out.put(bytes); + } + } + + public void entry(int idx, Inspector inspector) { + encodeValue(inspector); + } + + public void field(int symbol, Inspector inspector) { + encode_cmpr_long(symbol); + encodeValue(inspector); + } +} |