예제 #1
0
        /// <summary>
        /// Adds a key with the given index to the trie.
        /// </summary>
        /// <param name="index">
        /// The index of the root <see cref="BinaryTrieNode"/> for the given key value.
        /// </param>
        /// <param name="key">An <see cref="Int32"/> key value.</param>
        /// <param name="keyLength">
        /// The length in bits of the significant portion of the key.
        /// </param>
        /// <returns>The <see cref="BinaryTrieNode"/> that was added to the trie.</returns>
        protected BinaryTrieNode AddInternal(Int32 index, Int32 key, Int32 keyLength)
        {
            CountInternal++;
            BinaryTrieNode root = Roots[index];

            if (null == root)
            {
                // Create the new root.
                return(_roots[index] = new BinaryTrieNode(key, keyLength));
            }
            else
            {
                // Add the record to the trie.
                return(root.AddInternal(key, keyLength));
            }
        }
예제 #2
0
        /// <summary>
        /// Adds a record to the trie using the internal representation of an IP address.
        /// </summary>
        internal BinaryTrieNode AddInternal(Int32 key, Int32 keyLength)
        {
            // Find the common key keyLength
            Int32 difference = key ^ _key;
            // We are only interested in matches up to the keyLength...
            Int32 commonKeyLength = Math.Min(_keyLength, keyLength);

            // ...so count down from there.
            while (difference >= _bit[commonKeyLength])
            {
                commonKeyLength--;
            }

            // If the new key length is smaller than the common key length,
            // or equal but smaller than the current key length,
            // the new key should be the parent of the current node.
            if ((keyLength < commonKeyLength) || ((keyLength == commonKeyLength) && (keyLength < _keyLength)))
            {
                // Make a copy that will be the child node.
                BinaryTrieNode copy = (BinaryTrieNode)this.MemberwiseClone();                 // new BinaryTrieNode(this);
                // Fill in the child references based on the first bit after the common key.
                if ((_key & _bit[keyLength + 1]) != 0)
                {
                    _zero = null;
                    _one  = copy;
                }
                else
                {
                    _zero = copy;
                    _one  = null;
                }
                _key       = key;
                _keyLength = keyLength;
                UserData   = EmptyData;
                return(this);
            }

            // Do we have a complete match?
            if (commonKeyLength == _keyLength)
            {
                if (keyLength == _keyLength)
                {
                    return(this);
                }

                // Yes. Add the key as a child.
                if ((key & _bit[_keyLength + 1]) == 0)
                {
                    // The remainder of the key starts with a zero.
                    // Do we have a child in this position?
                    if (null == _zero)
                    {
                        // No. Create one.
                        return(_zero = new BinaryTrieNode(key, keyLength));
                    }
                    else
                    {
                        // Yes. Add this key to the child.
                        return(_zero.AddInternal(key, keyLength));
                    }
                }
                else
                {
                    // The remainder of the key starts with a one.
                    // Do we have a child in this position?
                    if (null == _one)
                    {
                        // No. Create one.
                        return(_one = new BinaryTrieNode(key, keyLength));
                    }
                    else
                    {
                        // Yes. Add this key to the child.
                        return(_one.AddInternal(key, keyLength));
                    }
                }
            }
            else
            {
                // No. The match is only partial, so split this node.
                // Make a copy that will be the first child node.
                BinaryTrieNode copy = (BinaryTrieNode)this.MemberwiseClone();                 // new BinaryTrieNode(this);
                // And create the other child node.
                BinaryTrieNode newEntry = new BinaryTrieNode(key, keyLength);
                // Fill in the child references based on the first
                // bit after the common key.
                if ((_key & _bit[commonKeyLength + 1]) != 0)
                {
                    _zero = newEntry;
                    _one  = copy;
                }
                else
                {
                    _zero = copy;
                    _one  = newEntry;
                }
                _keyLength = commonKeyLength;
                return(newEntry);
            }
        }