aboutsummaryrefslogtreecommitdiffstats
path: root/vespajlib/src/main/java/com/yahoo/slime/ArrayValue.java
diff options
context:
space:
mode:
authorHåvard Pettersen <havardpe@yahooinc.com>2023-03-16 12:05:19 +0000
committerHåvard Pettersen <havardpe@yahooinc.com>2023-03-16 16:14:14 +0000
commitd3834a494402a3ad3c7f1b9f47793b1b90cbbb18 (patch)
tree54011699949d51150598f21b57c7b46637380819 /vespajlib/src/main/java/com/yahoo/slime/ArrayValue.java
parent33118797862c2025aeafdf11422754e6df4396fc (diff)
auto-detect arrays of long or double
Diffstat (limited to 'vespajlib/src/main/java/com/yahoo/slime/ArrayValue.java')
-rw-r--r--vespajlib/src/main/java/com/yahoo/slime/ArrayValue.java107
1 files changed, 90 insertions, 17 deletions
diff --git a/vespajlib/src/main/java/com/yahoo/slime/ArrayValue.java b/vespajlib/src/main/java/com/yahoo/slime/ArrayValue.java
index dbd9771afe9..684483cb877 100644
--- a/vespajlib/src/main/java/com/yahoo/slime/ArrayValue.java
+++ b/vespajlib/src/main/java/com/yahoo/slime/ArrayValue.java
@@ -6,9 +6,93 @@ package com.yahoo.slime;
*/
final class ArrayValue extends Value {
- private int capacity = 16;
+ static final int initial_capacity = 16;
+
+ private interface Impl {
+ public void prepareFor(ArrayValue self, Type type);
+ public Value add(Value value, int used);
+ public Value get(int index);
+ }
+
+ private static final class EmptyImpl implements Impl {
+ public void prepareFor(ArrayValue self, Type type) {
+ if (type == Type.LONG) {
+ self.impl = new LongImpl();
+ } else if (type == Type.DOUBLE) {
+ self.impl = new DoubleImpl();
+ } else {
+ self.impl = new GenericImpl(this, 0);
+ }
+ }
+ public Value add(Value value, int used) { return NixValue.invalid(); }
+ public Value get(int index) { return NixValue.invalid(); }
+ }
+
+ private static final class LongImpl implements Impl {
+ private long[] values = new long[initial_capacity];
+ public void prepareFor(ArrayValue self, Type type) {
+ if (type != Type.LONG) {
+ self.impl = new GenericImpl(this, self.used);
+ }
+ }
+ public Value add(Value value, int used) {
+ if (used == values.length) {
+ long[] v = values;
+ values = new long[v.length << 1];
+ System.arraycopy(v, 0, values, 0, used);
+ }
+ values[used] = value.asLong();
+ return get(used);
+ }
+ public Value get(int index) { return new LongValue(values[index]); }
+ }
+
+ private static final class DoubleImpl implements Impl {
+ private double[] values = new double[initial_capacity];
+ public void prepareFor(ArrayValue self, Type type) {
+ if (type != Type.DOUBLE) {
+ self.impl = new GenericImpl(this, self.used);
+ }
+ }
+ public Value add(Value value, int used) {
+ if (used == values.length) {
+ double[] v = values;
+ values = new double[v.length << 1];
+ System.arraycopy(v, 0, values, 0, used);
+ }
+ values[used] = value.asDouble();
+ return get(used);
+ }
+ public Value get(int index) { return new DoubleValue(values[index]); }
+ }
+
+ private static final class GenericImpl implements Impl {
+ private Value[] values;
+ GenericImpl(Impl src, int len) {
+ int capacity = initial_capacity;
+ while (capacity < (len + 1)) {
+ capacity = capacity << 1;
+ }
+ values = new Value[capacity];
+ for (int i = 0; i < len; i++) {
+ values[i] = src.get(i);
+ }
+ }
+ public void prepareFor(ArrayValue self, Type type) {}
+ public Value add(Value value, int used) {
+ if (used == values.length) {
+ Value[] v = values;
+ values = new Value[v.length << 1];
+ System.arraycopy(v, 0, values, 0, used);
+ }
+ values[used] = value;
+ return get(used);
+ }
+ public Value get(int index) { return values[index]; }
+ }
+
+ private Impl impl = new EmptyImpl();
private int used = 0;
- private Value[] values = new Value[capacity];
private final SymbolTable names;
public ArrayValue(SymbolTable names) { this.names = names; }
@@ -16,33 +100,22 @@ final class ArrayValue extends Value {
public int children() { return used; }
public int entries() { return used; }
public Value entry(int index) {
- return (index < used) ? values[index] : NixValue.invalid();
+ return (index >= 0 && index < used) ? impl.get(index) : NixValue.invalid();
}
public void accept(Visitor v) { v.visitArray(this); }
public void traverse(ArrayTraverser at) {
for (int i = 0; i < used; i++) {
- at.entry(i, values[i]);
+ at.entry(i, impl.get(i));
}
}
- private void grow() {
- Value[] v = values;
- capacity = (capacity << 1);
- values = new Value[capacity];
- System.arraycopy(v, 0, values, 0, used);
- }
-
protected Value addLeaf(Value value) {
- if (used == capacity) {
- grow();
- }
- values[used++] = value;
- return value;
+ impl.prepareFor(this, value.type());
+ return impl.add(value, used++);
}
public Value addArray() { return addLeaf(new ArrayValue(names)); }
public Value addObject() { return addLeaf(new ObjectValue(names)); }
-
}