private Node GetRange(PrefixKey key, int range, out TValue lastMatch, out int depth) { Node cursor = _root; depth = 0; PrefixKey xor = key ^ cursor.Key; var match = true; lastMatch = null; while (depth < range && match) { if (depth < cursor.Range) { if (match = !xor.IsSetAt(depth)) { depth++; } } else { // remember the last match lastMatch = cursor.Data ?? lastMatch; // advance to the next nod var nextIndex = key.ChildIndex(depth); var next = cursor[nextIndex]; if (next != null) { cursor = next; // Contract.Assert(cursor.Range > depth); xor = key ^ cursor.Key; depth++; } else { match = false; } } } // Contract.Assert(this.Depth0IffRoot(cursor, depth)); // Contract.Assert(this.OnlyEndDigitIsDifferentIfNotRoot(cursor, key, range, depth)); if (depth == cursor.Range) { lastMatch = cursor.Data ?? lastMatch; } return(cursor); }
public TValue Insert(PrefixKey key, int range, TValue value, int depth) { // This node is an exact "prefix" match, this might mean one of the special case applies if (Range == depth) { // prefix is already covered by node, this is an null op if (Data == value) { return(value); } if (range == Range) { // same range, but data is different, this means replacement Data = value; return(value); } } // Contract.Assert(range == depth || Range == depth || key.IsSetAt(depth) != Key.IsSetAt(depth)); // split this node if needed if (Range > depth) { var clone = new Node(Key, Range, Data, _children); Data = null; Range = depth; _children = new Node[2]; this[Key.ChildIndex(depth)] = clone; } if (Range == range) { // where the node split is exactly the new node is supposed to be Key = key; Data = value; } else { var newChildIndex = key.ChildIndex(depth); // Contract.Assert(this[newChildIndex] == null); var newNode = new Node(key, range, value); this[newChildIndex] = newNode; } return(null); }