Experimental trie implementation
diff --git a/utils/trie.h b/utils/trie.h
new file mode 100644
index 0000000..0e1a330
--- /dev/null
+++ b/utils/trie.h
@@ -0,0 +1,386 @@
+/* -*-  Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2011 University of California, Los Angeles
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation;
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ * Author: Alexander Afanasyev <alexander.afanasyev@ucla.edu>
+ */
+
+#include "ns3/core-module.h"
+#include "ns3/ndnSIM-module.h"
+
+#include <boost/intrusive/unordered_set.hpp>
+#include <boost/functional/hash.hpp>
+
+namespace bi = boost::intrusive;
+
+/////////////////////////////////////////////////////
+// Allow customization for payload
+//
+template<typename Payload>
+struct pointer_payload_traits
+{
+  typedef Payload*        pointer_type;
+  typedef const Payload*  const_pointer_type;
+
+  static const Payload* empty_payload;
+};
+
+template<typename Payload>
+const Payload*
+pointer_payload_traits<Payload>::empty_payload = 0;
+
+template<typename Payload>
+struct smart_pointer_payload_traits
+{
+  typedef ns3::Ptr<Payload>       pointer_type;
+  typedef ns3::Ptr<const Payload> const_pointer_type;
+  
+  static const ns3::Ptr<const Payload> empty_payload;
+};
+
+template<typename Payload>
+const ns3::Ptr<const Payload>
+smart_pointer_payload_traits<Payload>::empty_payload = 0;
+
+
+////////////////////////////////////////////////////
+// forward declarations
+//
+template<typename FullKey, typename Payload, typename PayloadTraits = pointer_payload_traits<Payload> >
+class trie; 
+
+template<typename FullKey, typename Payload, typename PayloadTraits>
+inline std::ostream&
+operator << (std::ostream &os, const trie<FullKey, Payload, PayloadTraits> &trie_node);
+
+template<typename FullKey, typename Payload, typename PayloadTraits>
+bool
+operator== (const trie<FullKey, Payload, PayloadTraits> &a, const trie<FullKey, Payload, PayloadTraits> &b);
+
+template<typename FullKey, typename Payload, typename PayloadTraits >
+std::size_t
+hash_value (const trie<FullKey, Payload, PayloadTraits> &trie_node);
+
+///////////////////////////////////////////////////
+// actual definition
+//
+
+
+template<typename FullKey,
+	 typename Payload, typename PayloadTraits>
+class trie
+{
+public:
+  typedef typename FullKey::partial_type Key;
+
+  typedef trie*       iterator;
+  typedef const trie* const_iterator;
+  
+  inline
+  trie (const Key &key, size_t bucketSize = 10, size_t bucketIncrement = 10);
+
+  inline
+  ~trie ();
+  
+  // actual entry
+  friend bool
+  operator== <> (const trie<FullKey, Payload, PayloadTraits> &a, const trie<FullKey, Payload, PayloadTraits> &b);
+
+  friend std::size_t
+  hash_value <> (const trie<FullKey, Payload, PayloadTraits> &trie_node);
+
+  inline std::pair<iterator, bool>
+  insert (const FullKey &key, typename PayloadTraits::const_pointer_type payload);
+
+  /**
+   * @brief Removes payload (if it exists) and if there are no children, prunes parents trie
+   */
+  inline void
+  erase ();
+
+  /**
+   * @brief Do exactly as erase, but without erasing the payload
+   */
+  inline void
+  prune ();
+
+  /**
+   * @brief Perform the longest prefix match
+   * @param key the key for which to perform the longest prefix match
+   *
+   * @return ->second is true if prefix in ->first is longer than key
+   */
+  inline boost::tuple<iterator, bool, iterator>
+  find (const FullKey &key);
+
+  /**
+   * @brief Find next payload of the sub-trie
+   * @returns end() or a valid iterator pointing to the trie leaf (order is not defined, enumeration )
+   */
+  inline iterator
+  find ();
+
+  /**
+   * @brief Find next payload of the sub-trie satisfying the predicate
+   * @param pred predicate
+   * @returns end() or a valid iterator pointing to the trie leaf (order is not defined, enumeration )
+   */
+  template<class Predicate>
+  inline iterator
+  find_if (Predicate pred);
+
+  iterator end ()
+  {
+    return 0;
+  }
+
+  const_iterator end () const
+  {
+    return 0;
+  }
+  
+  // inline const_iterator
+  // find () const;
+  
+private:
+  //The disposer object function
+  struct trie_delete_disposer
+  {
+    void operator() (trie *delete_this)
+    {
+      // std::cout << "Deleting " << delete_this << "\n";
+      delete delete_this;
+    }
+  };  
+
+  friend
+  std::ostream&
+  operator<< < > (std::ostream &os, const trie &trie_node);
+  
+private:
+  bi::unordered_set_member_hook<> member_hook_;
+
+  // necessary typedefs
+  typedef trie self_type;
+  typedef bi::member_hook< trie,
+  			   bi::unordered_set_member_hook< >, &trie::member_hook_ > member_hook;
+  typedef bi::unordered_set< trie, member_hook >                                   unordered_set;
+  typedef typename unordered_set::bucket_type   bucket_type;
+  typedef typename unordered_set::bucket_traits bucket_traits;
+
+  ////////////////////////////////////////////////
+  // Actual data
+  ////////////////////////////////////////////////
+  
+  Key key_; ///< name component
+
+  size_t initialBucketSize_;
+  size_t bucketIncrement_;
+
+  size_t bucketSize_;
+  bucket_type *buckets_;
+  unordered_set children_;
+  
+  typename PayloadTraits::const_pointer_type payload_;
+  trie *parent_; // to make cleaning effective
+};
+
+template<typename FullKey, typename Payload, typename PayloadTraits>
+trie<FullKey, Payload, PayloadTraits>::trie (const trie::Key &key, size_t bucketSize, size_t bucketIncrement)
+  : key_ (key)
+  , initialBucketSize_ (bucketSize)
+  , bucketIncrement_ (bucketIncrement)
+  , bucketSize_ (initialBucketSize_)
+  , buckets_ (new bucket_type [bucketSize_])
+  , children_ (bucket_traits (buckets_, bucketSize_))
+  , payload_ (PayloadTraits::empty_payload)
+  , parent_ (0)
+{
+}
+
+template<typename FullKey, typename Payload, typename PayloadTraits>
+trie<FullKey, Payload, PayloadTraits>::~trie ()
+{
+  children_.clear_and_dispose (trie_delete_disposer ());
+  delete [] buckets_;
+}
+
+template<typename FullKey, typename Payload, typename PayloadTraits>
+inline
+std::pair<typename trie<FullKey, Payload, PayloadTraits>::iterator, bool>
+trie<FullKey, Payload, PayloadTraits>::insert (const FullKey &key, typename PayloadTraits::const_pointer_type payload)
+{
+  trie *trieNode = this;
+  
+  BOOST_FOREACH (const Key &subkey, key)
+    {
+      typename unordered_set::iterator item = trieNode->children_.find (subkey);
+      if (item == trieNode->children_.end ())
+	{
+	  trie *newNode = new trie (subkey, initialBucketSize_, bucketIncrement_);
+	  // std::cout << "new " << newNode << "\n";
+	  newNode->parent_ = trieNode;
+
+	  if (trieNode->children_.size () > trieNode->bucketSize_)
+	    {
+	      trieNode->bucketSize_ += trieNode->bucketIncrement_;
+	      bucket_type *newBuckets = new bucket_type [trieNode->bucketSize_];
+	      trieNode->children_.rehash (bucket_traits (newBuckets, trieNode->bucketSize_));
+	      delete [] trieNode->buckets_;
+	      trieNode->buckets_ = newBuckets;
+	    }
+	  
+	  std::pair< typename unordered_set::iterator, bool > ret =
+	    trieNode->children_.insert (*newNode);
+	  
+	  trieNode = &(*ret.first);
+	}
+      else
+	trieNode = &(*item);
+    }
+
+  if (trieNode->payload_ == 0)
+    {
+      trieNode->payload_ = payload;
+      return std::make_pair (trieNode, true);
+    }
+  else
+    return std::make_pair (trieNode, false);
+}
+
+template<typename FullKey, typename Payload, typename PayloadTraits>
+inline
+boost::tuple<typename trie<FullKey, Payload, PayloadTraits>::iterator,
+	     bool,
+	     typename trie<FullKey, Payload, PayloadTraits>::iterator>
+trie<FullKey, Payload, PayloadTraits>::find (const FullKey &key)
+{
+  trie *trieNode = this;
+  iterator foundNode = (payload_ != PayloadTraits::empty_payload) ? this : 0;
+  bool reachLast = true;
+  
+  BOOST_FOREACH (const Key &subkey, key)
+    {
+      typename unordered_set::iterator item = trieNode->children_.find (subkey);
+      if (item == trieNode->children_.end ())
+	{
+	  reachLast = false;
+	  break;
+	}
+      else
+	{
+	  trieNode = &(*item);
+	  
+	  if (trieNode->payload_ != PayloadTraits::empty_payload)
+	    foundNode = trieNode;
+	}
+    }
+
+  return boost::make_tuple (foundNode, reachLast, trieNode);  
+}
+
+template<typename FullKey, typename Payload, typename PayloadTraits>
+inline typename trie<FullKey, Payload, PayloadTraits>::iterator
+trie<FullKey, Payload, PayloadTraits>::find ()
+{
+  if (payload_ != PayloadTraits::empty_payload)
+    return this;
+
+  typedef trie<FullKey, Payload, PayloadTraits> trie;
+  BOOST_FOREACH (const trie &subnode, children_)
+    {
+      iterator value = subnode.find ();
+      if (value != 0)
+	return value;
+    }
+  
+  return 0;
+}
+
+template<typename FullKey, typename Payload, typename PayloadTraits>
+template<class Predicate>
+inline typename trie<FullKey, Payload, PayloadTraits>::iterator
+trie<FullKey, Payload, PayloadTraits>::find_if (Predicate pred)
+{
+  if (payload_ != PayloadTraits::empty_payload && pred (payload_))
+    return this;
+
+  typedef trie<FullKey, Payload, PayloadTraits> trie;
+  BOOST_FOREACH (const trie &subnode, children_)
+    {
+      iterator value = subnode.find ();
+      if (value != 0)
+	return value;
+    }
+  
+  return 0;
+}
+
+
+template<typename FullKey, typename Payload, typename PayloadTraits>
+inline void
+trie<FullKey, Payload, PayloadTraits>::erase ()
+{
+  payload_ = PayloadTraits::empty_payload;
+  prune ();
+}
+
+template<typename FullKey, typename Payload, typename PayloadTraits>
+inline void
+trie<FullKey, Payload, PayloadTraits>::prune ()
+{
+  if (payload_ == 0 && children_.size () == 0)
+    {
+      if (parent_ == 0) return;
+
+      trie *parent = parent_;
+      parent->children_.erase_and_dispose (*this, trie_delete_disposer ()); // delete this; basically, committing a suicide
+
+      parent->prune ();
+    }
+}
+
+template<typename FullKey, typename Payload, typename PayloadTraits>
+inline std::ostream&
+operator << (std::ostream &os, const trie<FullKey, Payload, PayloadTraits> &trie_node)
+{
+  os << "# " << trie_node.key_ << ((trie_node.payload_ != 0)?"*":"") << std::endl;
+  typedef trie<FullKey, Payload, PayloadTraits> trie;
+  BOOST_FOREACH (const trie &subnode, trie_node.children_)
+    {
+      os << "\"" << &trie_node << "\"" << " [label=\"" << trie_node.key_ << ((trie_node.payload_ != 0)?"*":"") << "\"]\n";
+      os << "\"" << &subnode << "\"" << " [label=\"" << subnode.key_ << ((subnode.payload_ != 0)?"*":"") << "\"]""\n";
+      
+      os << "\"" << &trie_node << "\"" << " -> " << "\"" << &subnode << "\"" << "\n";
+      os << subnode;
+    }
+
+  return os;
+}
+
+template<typename FullKey, typename Payload, typename PayloadTraits>
+inline bool
+operator == (const trie<FullKey, Payload, PayloadTraits> &a, const trie<FullKey, Payload, PayloadTraits> &b)
+{
+  return a.key_ == b.key_;
+}
+
+template<typename FullKey, typename Payload, typename PayloadTraits>
+inline std::size_t
+hash_value (const trie<FullKey, Payload, PayloadTraits> &trie_node)
+{
+  return boost::hash_value (trie_node.key_);
+}