summaryrefslogtreecommitdiffstats
path: root/vespajlib/src/main/java/com/yahoo/slime/BinaryEncoder.java
diff options
context:
space:
mode:
authorJon Bratseth <bratseth@yahoo-inc.com>2016-06-15 23:09:44 +0200
committerJon Bratseth <bratseth@yahoo-inc.com>2016-06-15 23:09:44 +0200
commit72231250ed81e10d66bfe70701e64fa5fe50f712 (patch)
tree2728bba1131a6f6e5bdf95afec7d7ff9358dac50 /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.java144
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);
+ }
+}