/// <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)); } }
/// <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); } }