예제 #1
0
        private static int IndexOfNull <TValue>(
            byte[] buffer,
            int index,
            int count,
            ref BsonTrieNode <TValue> bsonTrieNode)
        {
            for (; count > 0; index++, count--)
            {
                // bsonTrieNode might be null on entry or it might become null while navigating the trie
                if (bsonTrieNode == null)
                {
                    return(Array.IndexOf <byte>(buffer, 0, index, count));
                }

                var keyByte = buffer[index];
                if (keyByte == 0)
                {
                    return(index);
                }

                bsonTrieNode = bsonTrieNode.GetChild(keyByte); // might return null
            }

            return(-1);
        }
예제 #2
0
        /// <summary>
        /// Gets the node associated with the specified element name.
        /// </summary>
        /// <param name="utf8">The element name.</param>
        /// <param name="node">
        /// When this method returns, contains the node associated with the specified element name, if the key is found;
        /// otherwise, null. This parameter is passed unitialized.
        /// </param>
        /// <returns>True if the node was found; otherwise, false.</returns>
        public bool TryGetNode(ArraySegment <byte> utf8, out BsonTrieNode <TValue> node)
        {
            node = _root;
            for (var i = 0; node != null && i < utf8.Count; i++)
            {
                var keyByte = utf8.Array[utf8.Offset + i];
                node = node.GetChild(keyByte);
            }

            return(node != null);
        }
예제 #3
0
        /// <summary>
        /// Tries to get the node associated with a name read from a stream.
        /// </summary>
        /// <param name="stream">The stream.</param>
        /// <param name="node">The node.</param>
        /// <returns>
        /// True if the node was found.
        /// If the node was found the stream is advanced over the name, otherwise
        /// the stream is repositioned to the beginning of the name.
        /// </returns>
        public bool TryGetNode(BsonStream stream, out BsonTrieNode <TValue> node)
        {
            var position = stream.Position;
            var utf8     = stream.ReadCStringBytes();

            if (TryGetNode(utf8, out node))
            {
                return(true);
            }

            stream.Position = position;
            return(false);
        }
예제 #4
0
        // public methods
        /// <summary>
        /// Adds the specified elementName (after encoding as a UTF8 byte sequence) and value to the trie.
        /// </summary>
        /// <param name="elementName">The element name to add.</param>
        /// <param name="value">The value to add. The value can be null for reference types.</param>
        public void Add(string elementName, TValue value)
        {
            var keyBytes = __utf8Encoding.GetBytes(elementName);

            var node = _root;
            foreach (var keyByte in keyBytes)
            {
                var child = node.GetChild(keyByte);
                if (child == null)
                {
                    child = new BsonTrieNode<TValue>(keyByte);
                    node.AddChild(child);
                }
                node = child;
            }

            node.SetValue(elementName, value);
        }
예제 #5
0
        // public methods
        /// <summary>
        /// Adds the specified elementName (after encoding as a UTF8 byte sequence) and value to the trie.
        /// </summary>
        /// <param name="elementName">The element name to add.</param>
        /// <param name="value">The value to add. The value can be null for reference types.</param>
        public void Add(string elementName, TValue value)
        {
            using var rentedSegment = Utf8Encodings.Strict.GetBytesUsingThreadStaticBuffer(elementName);

            var node = _root;

            foreach (var keyByte in rentedSegment.Segment)
            {
                var child = node.GetChild(keyByte);
                if (child == null)
                {
                    child = new BsonTrieNode <TValue>(keyByte);
                    node.AddChild(child);
                }
                node = child;
            }

            node.SetValue(elementName, value);
        }
예제 #6
0
 // constructors
 /// <summary>
 /// Initializes a new instance of the BsonTrie class.
 /// </summary>
 public BsonTrie()
 {
     _root = new BsonTrieNode <TValue>(0);
 }
예제 #7
0
        // internal methods
        internal void AddChild(BsonTrieNode <TValue> child)
        {
            if (GetChild(child._keyByte) != null)
            {
                throw new ArgumentException("BsonTrieNode already contains a child with the same keyByte.");
            }

            if (_children != null)
            {
                // add a new child to the existing _children
                var children = new BsonTrieNode <TValue> [_children.Length + 1];
                Array.Copy(_children, children, _children.Length);
                children[children.Length - 1] = child;

                var childrenIndexes = _childrenIndexes;
                var minChildKeyByte = _minChildKeyByte;
                var maxChildKeyByte = _minChildKeyByte + _childrenIndexes.Length - 1;

                // if new keyByte doesn't fall within existing min/max range expand the range
                if (child._keyByte < minChildKeyByte)
                {
                    // grow the indexes on the min side
                    minChildKeyByte = child._keyByte;
                    childrenIndexes = new byte[maxChildKeyByte - minChildKeyByte + 1];
                    var sizeDelta = childrenIndexes.Length - _childrenIndexes.Length;
                    for (var i = 0; i < sizeDelta; i++)
                    {
                        childrenIndexes[i] = 255;
                    }
                    Array.Copy(_childrenIndexes, 0, childrenIndexes, sizeDelta, _childrenIndexes.Length);
                }
                else if (child._keyByte > maxChildKeyByte)
                {
                    // grow the indexes on the max side
                    maxChildKeyByte = child._keyByte;
                    childrenIndexes = new byte[maxChildKeyByte - minChildKeyByte + 1];
                    Array.Copy(_childrenIndexes, 0, childrenIndexes, 0, _childrenIndexes.Length);
                    for (var i = _childrenIndexes.Length; i < childrenIndexes.Length; i++)
                    {
                        childrenIndexes[i] = 255;
                    }
                }
                childrenIndexes[child._keyByte - minChildKeyByte] = (byte)(children.Length - 1);

                _children        = children;
                _childrenIndexes = childrenIndexes;
                _minChildKeyByte = minChildKeyByte;
            }
            else if (_onlyChild != null)
            {
                // switch from having an _onlyChild to having two _children
                var children = new BsonTrieNode <TValue> [2];
                children[0] = _onlyChild;
                children[1] = child;

                var minChildKeyByte = _onlyChild._keyByte;
                var maxChildKeyByte = child._keyByte;
                if (minChildKeyByte > maxChildKeyByte)
                {
                    minChildKeyByte = child._keyByte;
                    maxChildKeyByte = _onlyChild._keyByte;
                }

                var childrenIndexes = new byte[maxChildKeyByte - minChildKeyByte + 1];
                for (var i = 0; i < childrenIndexes.Length; i++)
                {
                    childrenIndexes[i] = 255;
                }
                childrenIndexes[_onlyChild._keyByte - minChildKeyByte] = 0;
                childrenIndexes[child._keyByte - minChildKeyByte]      = 1;

                _onlyChild       = null;
                _children        = children;
                _childrenIndexes = childrenIndexes;
                _minChildKeyByte = minChildKeyByte;
            }
            else
            {
                _onlyChild = child;
            }
        }