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/ObjectValue.java |
Publish
Diffstat (limited to 'vespajlib/src/main/java/com/yahoo/slime/ObjectValue.java')
-rw-r--r-- | vespajlib/src/main/java/com/yahoo/slime/ObjectValue.java | 108 |
1 files changed, 108 insertions, 0 deletions
diff --git a/vespajlib/src/main/java/com/yahoo/slime/ObjectValue.java b/vespajlib/src/main/java/com/yahoo/slime/ObjectValue.java new file mode 100644 index 00000000000..3d8b54ed294 --- /dev/null +++ b/vespajlib/src/main/java/com/yahoo/slime/ObjectValue.java @@ -0,0 +1,108 @@ +// Copyright 2016 Yahoo Inc. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. +package com.yahoo.slime; + +/** + * A Value holding a slime "Object", a dynamic collection of named + * value fields. Fields can be inspected or traversed using the + * {@link Inspector} interface, and you can add new fields by using the + * various "set" methods in the @ref Cursor interface. + **/ +final class ObjectValue extends Value { + + private int capacity = 16; + private int hashSize() { return (capacity + (capacity >> 1) - 1); } + private int used = 0; + private Value[] values = new Value[capacity]; + private int[] hash = new int[capacity + hashSize() + (capacity << 1)]; + private final SymbolTable names; + + private final void rehash() { + capacity = (capacity << 1); + Value[] v = values; + values = new Value[capacity]; + System.arraycopy(v, 0, values, 0, used); + int[] h = hash; + hash = new int[capacity + hashSize() + (capacity << 1)]; + System.arraycopy(h, 0, hash, 0, used); + for (int i = 0; i < used; i++) { + int prev = (capacity + (hash[i] % hashSize())); + int entry = hash[prev]; + while (entry != 0) { + prev = entry + 1; + entry = hash[prev]; + } + final int insertIdx = (capacity + hashSize() + (i << 1)); + hash[prev] = insertIdx; + hash[insertIdx] = i; + } + } + + private final Value put(int sym, Value value) { + if (used == capacity) { + rehash(); + } + int prev = (capacity + (sym % hashSize())); + int entry = hash[prev]; + while (entry != 0) { + final int idx = hash[entry]; + if (hash[idx] == sym) { // found entry + return NixValue.invalid(); + } + prev = entry + 1; + entry = hash[prev]; + } + final int insertIdx = (capacity + hashSize() + (used << 1)); + hash[prev] = insertIdx; + hash[insertIdx] = used; + hash[used] = sym; + values[used++] = value; + return value; + } + + private final Value get(int sym) { + int entry = hash[capacity + (sym % hashSize())]; + while (entry != 0) { + final int idx = hash[entry]; + if (hash[idx] == sym) { // found entry + return values[idx]; + } + entry = hash[entry + 1]; + } + return NixValue.invalid(); + } + + public ObjectValue(SymbolTable names) { this.names = names; } + public ObjectValue(SymbolTable names, int sym, Value value) { + this.names = names; + put(sym, value); + } + + public final Type type() { return Type.OBJECT; } + public final int children() { return used; } + public final int fields() { return used; } + + public final Value field(int sym) { return get(sym); } + public final Value field(String name) { return get(names.lookup(name)); } + + public final void accept(Visitor v) { v.visitObject(this); } + + public final void traverse(ObjectSymbolTraverser ot) { + for (int i = 0; i < used; ++i) { + ot.field(hash[i], values[i]); + } + } + + public final void traverse(ObjectTraverser ot) { + for (int i = 0; i < used; ++i) { + ot.field(names.inspect(hash[i]), values[i]); + } + } + + protected final Cursor setLeaf(int sym, Value value) { return put(sym, value); } + public final Cursor setArray(int sym) { return put(sym, new ArrayValue(names)); } + public final Cursor setObject(int sym) { return put(sym, new ObjectValue(names)); } + + protected final Cursor setLeaf(String name, Value value) { return put(names.insert(name), value); } + public final Cursor setArray(String name) { return put(names.insert(name), new ArrayValue(names)); } + public final Cursor setObject(String name) { return put(names.insert(name), new ObjectValue(names)); } +} |