xapi.collect.trie.DeepTrieEdge Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of xapi-core-collect Show documentation
Show all versions of xapi-core-collect Show documentation
Core interfaces for our collections api.
package xapi.collect.trie;
import xapi.collect.api.StringTrie;
import xapi.collect.api.StringTrie.StringTrieCursor;
import xapi.collect.api.StringTrie.StringTrieEdge;
import xapi.util.impl.Chars;
import xapi.util.impl.Chars.SingleChar;
public class DeepTrieEdge implements StringTrie.StringTrieEdge{
private static final SingleChar[] COMMON_CHARS = new SingleChar['_'];
static {
for (int i = '_';i-->0;)
COMMON_CHARS[i] = new SingleChar((char)i);
}
protected class DeepTrieCursor implements StringTrie.StringTrieCursor {
private final SingleChar key;
private final StringTrieEdge edge;
public DeepTrieCursor(char k, StringTrieEdge edge) {
if (k < COMMON_CHARS.length) {
this.key = COMMON_CHARS[k];
} else {
this.key = new Chars.SingleChar(k);
}
this.edge = edge;
}
@Override
public final CharSequence key() {
return key;
}
@Override
public final int consumed() {
return 1;
}
@Override
public final StringTrieEdge edge() {
return edge;
}
}
//The depth, in characters, for this element
private final int depth;
//The sequence of characters leading up to this node
private final CharSequence key;
//The value, if any, stored at this node
private volatile E value;
//Remember our highest and lowest chars to make add-to-either-end efficient
private volatile char lowest;
private volatile char highest;
//These are counts for the number of lower and higher elements
//We use char because there cannot be more array indices than there are chars.
private volatile char lowerUsed;
private volatile char higherUsed;
// // A cursor for speedy gets of the same value
// // This is not volatile because thread caching here is good.
// private int lastGet;
//The array
private StringTrieEdge[] edges;
public DeepTrieEdge(CharSequence key, int depth, E value) {
this(key, depth, value, 9);
}
@SuppressWarnings("unchecked")
public DeepTrieEdge(CharSequence key, int depth, E value, int initialSize) {
this.depth = depth;
this.key = key;
this.value = value;
this.edges = new StringTrieEdge[initialSize/2];
}
public synchronized DeepTrieEdge addEdge(StringTrieEdge edge) {
final CharSequence key = edge.key();
if (key.length() == 0) {
//we're adding another deep edge
} else {
final char k = key.charAt(0);
final int deltaLower = k - lowest;
if (deltaLower < 0) {
// we have a new lowest
lowest = k;
}
final int deltaHigher = k - highest;
if (deltaHigher > 0) {
// we have a new highest. First insert will go here.
highest = k;
}
// no easy insert; perform binary search
int pos = lowerUsed - 1;
StringTrieEdge biggestLow = edges[pos];
int deltaBottom;
searchLower:
if (biggestLow == null) {
deltaBottom = Integer.MIN_VALUE;
} else {
assert biggestLow.key().length() > 0;
char test = biggestLow.key().charAt(0);
deltaBottom = k - test;
if (deltaBottom == 0) {// optimistic search
addInto(biggestLow, edge);
return this;
}
if (deltaBottom < 0) {
// no need to consult highest. search down from our "highest lowest"
while (test > 0) {
if (--pos < 0)
break searchLower;
biggestLow = edges[pos];
if (biggestLow == null)
break searchLower;
test = biggestLow.key().charAt(0);
deltaBottom = k - test;
if (deltaBottom == 0) {
addInto(biggestLow, edge);
return this;
}
if (deltaBottom > 0) {
// inserted node is higher than this lowest
addAfterLower(biggestLow, edge, pos);
return this;
}
}
}
}
// Nothing found in lesser
// Start searching the higher
pos = edges.length - higherUsed;
StringTrieEdge lowestHigh = edges[pos];
int deltaTop;
searchHigher:
if (lowestHigh != null) {
assert lowestHigh.key().length() > 0;
char test = lowestHigh.key().charAt(0);
deltaTop = k - test;
if (deltaTop== 0) {// optimistic search
addInto(lowestHigh, edge);
return this;
}
if (deltaTop > 0) {
// we are greater than the lowest high value, so we must search
while (test > 0) {
if (++pos >= edges.length)
break searchHigher;
lowestHigh = edges[pos];
if (lowestHigh == null)
break searchHigher;
test = lowestHigh.key().charAt(0);
deltaTop = k - test;
if (deltaTop== 0) {
addInto(lowestHigh, edge);
return this;
}
if (deltaTop < 0) {
// inserted node is less than this highest
addBeforeHigher(lowestHigh, edge, pos);
return this;
}
}
// Inserted edge is greater
}
}
// Neither top nor bottom encloses this char,
// And it's not a max or min, thus, it must be between higher and lower.
// We choose to add it to the side that has the fewest elements
// TODO finish this
}
return this;
}
private void addBeforeHigher(StringTrieEdge biggestLow, StringTrieEdge edge, int pos) {
}
private void addAfterLower(StringTrieEdge biggestLow, StringTrieEdge edge, int pos) {
}
private void addInto(StringTrieEdge into, StringTrieEdge edge) {
}
@Override
public int depth() {
return depth;
}
@Override
public CharSequence key() {
return key;
}
@Override
public E value() {
return value;
}
@Override
public E addValue(CharSequence key, int keyFrom, E value) {
if (key.length() == 0 || keyFrom == key.length() - 1) {
E ret = this.value;
this.value = value;
return ret;
}
StringTrieCursor cursor = hasEdge(key, keyFrom);
if (cursor == null) {
} else {
StringTrieEdge into = cursor.edge();
return into.addValue(key, keyFrom+1, value);
}
return null;
}
@Override
public StringTrieCursor hasEdge(CharSequence key, int keyFrom) {
return null;
}
@Override
public StringTrieEdge highest() {
return edges[edges.length-1];
}
@Override
public StringTrieEdge lowest() {
return edges[0];
}
}