Example #1
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 </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 #2
0
        protected Object FindBestMatchInternal(Int32 index, Int32 key)
        {
            BinaryTrieNode root = _roots[index];

            if (null == root)
            {
                return(null);
            }
            return(root.FindBestMatch(key).UserData);
        }
Example #3
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></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 #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);
            }
        }