Go to the documentation of this file.00001 
00002 
00003 
00004 
00005 
00006 
00007 
00008 
00009 
00010 
00011 
00012 
00013 
00014 
00015 
00016 
00017 
00018 
00019 
00020 
00021 
00022 
00023 #ifndef _TRIE_H
00024 #define _TRIE_H
00025 
00026 #include <stdio.h>
00027 #include <stdlib.h>
00028 #include <string.h>
00029 
00030 #include "List.h"
00031 
00032 
00033 
00034 template<typename T>
00035 class Trie
00036 {
00037 public:
00038   Trie()
00039     {
00040       m_root.Clear();
00041     }
00042 
00043   
00044   
00045   bool Insert(const char *key, T *value, int rank, int key_len = -1);
00046 
00047   
00048   T* Search(const char *key, int key_len = -1) const;
00049   void Clear();
00050   void Print();
00051 
00052   bool Empty() const { return m_value_list.empty(); }
00053 
00054   virtual ~Trie() { Clear(); }
00055 
00056 private:
00057   static const int N_NODE_CHILDREN = 256;
00058 
00059   class Node
00060   {
00061   public:
00062     T* value;
00063     bool occupied;
00064     int rank;
00065 
00066     void Clear() {
00067       value = NULL;
00068       occupied = false;
00069       rank = 0;
00070       ink_zero(children);
00071     }
00072 
00073     void Print(const char *debug_tag) const;
00074     inline Node* GetChild(char index) const { return children[static_cast<unsigned char>(index)]; }
00075     inline Node* AllocateChild(char index) {
00076       Node * &child = children[static_cast<unsigned char>(index)];
00077       ink_assert(child == NULL);
00078       child = static_cast<Node*>(ats_malloc(sizeof(Node)));
00079       child->Clear();
00080       return child;
00081     }
00082 
00083   private:
00084     Node *children[N_NODE_CHILDREN];
00085   };
00086 
00087   Node m_root;
00088   Queue<T> m_value_list;
00089 
00090   void _CheckArgs(const char *key, int &key_len) const;
00091   void _Clear(Node *node);
00092 
00093   
00094   
00095   Trie(const Trie<T> &rhs) { };
00096   Trie &operator =(const Trie<T> &rhs) { return *this; }
00097 };
00098 
00099 template<typename T>
00100 void
00101 Trie<T>::_CheckArgs(const char *key, int &key_len) const
00102 {
00103   if (!key) {
00104     key_len = 0;
00105   }
00106   else if (key_len == -1) {
00107     key_len = strlen(key);
00108   }
00109 }
00110 
00111 template<typename T>
00112 bool
00113 Trie<T>::Insert(const char *key, T* value, int rank, int key_len )
00114 {
00115   _CheckArgs(key, key_len);
00116 
00117   Node *next_node;
00118   Node *curr_node = &m_root;
00119   int i = 0;
00120 
00121   while (true) {
00122     if (is_debug_tag_set("Trie::Insert")) {
00123       Debug("Trie::Insert", "Visiting Node...");
00124       curr_node->Print("Trie::Insert");
00125     }
00126 
00127     if (i == key_len) {
00128       break;
00129     }
00130 
00131     next_node = curr_node->GetChild(key[i]);
00132     if (!next_node) {
00133       while (i < key_len) {
00134         Debug("Trie::Insert", "Creating child node for char %c (%d)", key[i], key[i]);
00135         curr_node = curr_node->AllocateChild(key[i]);
00136         ++i;
00137       }
00138       break;
00139     }
00140     curr_node = next_node;
00141     ++i;
00142   }
00143 
00144   if (curr_node->occupied) {
00145     Debug("Trie::Insert", "Cannot insert duplicate!");
00146     return false;
00147   }
00148 
00149   curr_node->occupied = true;
00150   curr_node->value = value;
00151   curr_node->rank = rank;
00152   m_value_list.enqueue(curr_node->value);
00153   Debug("Trie::Insert", "inserted new element!");
00154   return true;
00155 }
00156 
00157 template<typename T>
00158 T*
00159 Trie<T>::Search(const char *key, int key_len ) const
00160 {
00161   _CheckArgs(key, key_len);
00162 
00163   const Node *found_node = 0;
00164   const Node *curr_node = &m_root;
00165   int i = 0;
00166 
00167   while (curr_node) {
00168     if (is_debug_tag_set("Trie::Search")) {
00169       Debug("Trie::Search", "Visiting node...");
00170       curr_node->Print("Trie::Search");
00171     }
00172     if (curr_node->occupied) {
00173       if (!found_node || curr_node->rank <= found_node->rank) {
00174         found_node = curr_node;
00175       }
00176     }
00177     if (i == key_len) {
00178       break;
00179     }
00180     curr_node = curr_node->GetChild(key[i]);
00181     ++i;
00182   }
00183 
00184   if (found_node) {
00185     Debug("Trie::Search", "Returning element with rank %d", found_node->rank);
00186     return found_node->value;
00187   }
00188 
00189   return NULL;
00190 }
00191 
00192 
00193 template<typename T>
00194 void
00195 Trie<T>::_Clear(Node *node)
00196 {
00197   Node *child;
00198 
00199   for (int i = 0; i < N_NODE_CHILDREN; ++i) {
00200     child = node->GetChild(i);
00201     if (child) {
00202       _Clear(child);
00203       ats_free(child);
00204     }
00205   }
00206 }
00207 
00208 template<typename T>
00209 void
00210 Trie<T>::Clear()
00211 {
00212   T* iter;
00213   while (NULL != (iter = m_value_list.pop()))
00214     delete iter;
00215 
00216   _Clear(&m_root);
00217   m_root.Clear();
00218 }
00219 
00220 template<typename T>
00221 void
00222 Trie<T>::Print() {
00223   
00224   forl_LL(T, iter, m_value_list)
00225     iter->Print();
00226 }
00227 
00228 template<typename T>
00229 void
00230 Trie<T>::Node::Print(const char *debug_tag) const
00231 {
00232   if (occupied) {
00233     Debug(debug_tag, "Node is occupied");
00234     Debug(debug_tag, "Node has rank %d", rank);
00235   } else {
00236     Debug(debug_tag, "Node is not occupied");
00237   }
00238 
00239   for (int i = 0; i < N_NODE_CHILDREN; ++i) {
00240     if (GetChild(i)) {
00241       Debug(debug_tag, "Node has child for char %c", static_cast<char>(i));
00242     }
00243   }
00244 }
00245 
00246 #endif // _TRIE_H