Experimental trie implementation
diff --git a/examples/trie.cc b/examples/trie.cc
new file mode 100644
index 0000000..4a70a87
--- /dev/null
+++ b/examples/trie.cc
@@ -0,0 +1,73 @@
+/* -*-  Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2012 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 "../utils/trie.h"
+
+using namespace ns3;
+
+NS_LOG_COMPONENT_DEFINE ("Trie");
+
+class Integer : public ns3::SimpleRefCount<Integer>
+{
+public:
+  Integer (int value) : value_ (value) {}
+  
+private:
+  int value_;
+};
+
+int
+main (int argc, char *argv[])
+{
+  trie<ns3::CcnxNameComponents, Integer, smart_pointer_payload_traits<Integer> > *x =
+    new trie<ns3::CcnxNameComponents, Integer, smart_pointer_payload_traits<Integer> >("root");
+
+  ns3::CcnxNameComponents n1,n2,n3,n5;
+  n1("a")("b")("c");
+  n2("a")("c");
+  n3("b")("c");
+  n5("a")("b");
+
+  ns3::Ptr<Integer> i = ns3::Create<Integer> (1);
+  x->insert (n1, i);
+  x->insert (n2, i);
+  x->insert (n3, i);
+  x->insert (n5, i);
+
+  ns3::CcnxNameComponents n4;
+  n4("a")("c");
+    
+  // std::cout << *x->find (n4).get<0> ();
+
+  x->prune ();
+  // x->find (n5).get<0> ()->erase ();
+  x->find (n1).get<0> ()->erase ();
+    
+  std::cout << "digraph trie {\n";
+  std::cout << *x;
+  std::cout << "}\n";
+
+  delete x;
+  
+  return 0;
+}
+
diff --git a/examples/wscript b/examples/wscript
index 1b064a3..7a49ca3 100644
--- a/examples/wscript
+++ b/examples/wscript
@@ -1,8 +1,11 @@
 # -*- Mode: python; py-indent-offset: 4; indent-tabs-mode: nil; coding: utf-8; -*-
 
 def build(bld):
-    obj = bld.create_ns3_program('ccnx-simple', ['NDNabstraction'])
+    obj = bld.create_ns3_program('ccnx-simple', ['ndnSIM'])
     obj.source = 'ccnx-simple.cc'
 
-    obj = bld.create_ns3_program('ccnx-grid', ['NDNabstraction', 'internet', 'point-to-point', 'point-to-point-layout'])
+    obj = bld.create_ns3_program('ccnx-grid', ['ndnSIM', 'point-to-point', 'point-to-point-layout'])
     obj.source = 'ccnx-grid.cc'
+
+    obj = bld.create_ns3_program('trie', ['ndnSIM'])
+    obj.source = 'trie.cc'
diff --git a/model/ccnx-name-components.h b/model/ccnx-name-components.h
index 7f62851..1d8ef2a 100644
--- a/model/ccnx-name-components.h
+++ b/model/ccnx-name-components.h
@@ -46,6 +46,9 @@
 class CcnxNameComponents : public SimpleRefCount<CcnxNameComponents>
 {
 public:
+  typedef std::list<std::string>::iterator       iterator;            
+  typedef std::list<std::string>::const_iterator const_iterator;
+
   /**
    * \brief Constructor 
    * Creates a prefix with zero components (can be looked as root "/")
@@ -109,6 +112,30 @@
   size () const;
 
   /**
+   * @brief Get read-write begin() iterator
+   */
+  inline iterator
+  begin ();
+
+  /**
+   * @brief Get read-only begin() iterator
+   */
+  inline const_iterator
+  begin () const;
+
+  /**
+   * @brief Get read-write end() iterator
+   */
+  inline iterator
+  end ();
+
+  /**
+   * @brief Get read-only end() iterator
+   */
+  inline const_iterator
+  end () const;
+
+  /**
    * \brief Equality operator for CcnxNameComponents
    */
   inline bool
@@ -119,12 +146,11 @@
    */
   inline bool
   operator< (const CcnxNameComponents &prefix) const;
+
+  typedef std::string partial_type;
   
 private:
   std::list<std::string> m_prefix;                              ///< \brief a list of strings (components)
-
-  typedef std::list<std::string>::iterator iterator;            
-  typedef std::list<std::string>::const_iterator const_iterator;
 };
 
 /**
@@ -149,6 +175,40 @@
   return m_prefix.size ();
 }
 
+CcnxNameComponents::iterator
+CcnxNameComponents::begin ()
+{
+  return m_prefix.begin ();
+}
+
+/**
+ * @brief Get read-only begin() iterator
+ */
+CcnxNameComponents::const_iterator
+CcnxNameComponents::begin () const
+{
+  return m_prefix.begin ();
+}  
+
+/**
+ * @brief Get read-write end() iterator
+ */
+CcnxNameComponents::iterator
+CcnxNameComponents::end ()
+{
+  return m_prefix.end ();
+}
+
+/**
+ * @brief Get read-only end() iterator
+ */
+CcnxNameComponents::const_iterator
+CcnxNameComponents::end () const
+{
+  return m_prefix.end ();
+}
+
+
 /**
  * \brief Generic constructor operator
  * The object of type T will be appended to the list of components
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_);
+}