Example #1
0
        /// <summary>
        /// Finds the exact internal match for a key.
        /// </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>
        /// <returns>A reference to the <see cref="Object"/> containing the key.</returns>
        protected Object FindExactMatchInternal(Int32 index, Int32 key)
        {
            BinaryTrieNode root = _roots[index];

            if (null == root)
            {
                return(null);
            }
            return(root.FindExactMatch(key).UserData);
        }
Example #2
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));
            }
        }
Example #3
0
        /// <summary>
        /// Attempts to find the country code corresponding to a given IP address.
        /// </summary>
        /// <param name="address">A <see cref="String"/> value representing the IP Address</param>
        /// <returns>The two letter country code corresponding to the IP address, or
        /// <strong>"??"</strong> if it was not found.
        /// </returns>
        public String GetCountry(String address)
        {
            String [] parts = address.Split('.');

            // The first IndexLength bits form the key into the array of root nodes.
            Int32 indexBase = ((Int32.Parse(parts[0]) << 8)
                               + Int32.Parse(parts[1]));
            Int32 index = indexBase >> (_indexOffset - 16);

            BinaryTrieNode root = base.Roots[index];

            // If we don't have a root, we don't have a value.
            if (null == root)
            {
                return(null);
            }

            // Calculate the full key...
            Int32 key = (indexBase << 16) + (Int32.Parse(parts[2]) << 8) + Int32.Parse(parts[3]);

            // ...and look it up.
            return((String)root.FindBestMatch(key).UserData);
        }
Example #4
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);
            }
        }
Example #5
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;
            }
        }
Example #6
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);
     }
 }