示例#1
0
        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);
        }
示例#2
0
            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);
            }