table: NameTree enumeration

refs #1318

Change-Id: I26f25cefe8f2939ca884103f1b081c0c02325207
diff --git a/daemon/table/fib.cpp b/daemon/table/fib.cpp
index 32aabbf..eea7641 100644
--- a/daemon/table/fib.cpp
+++ b/daemon/table/fib.cpp
@@ -87,13 +87,12 @@
 void
 Fib::removeNextHopFromAllEntries(shared_ptr<Face> face)
 {
-  shared_ptr<std::vector<shared_ptr<name_tree::Entry > > > nameTreeEntries =
-    m_nameTree.fullEnumerate(&predicate_NameTreeEntry_hasFibEntry);
-  for (size_t i = 0; i < nameTreeEntries->size(); ++i) {
-    shared_ptr<fib::Entry> entry = nameTreeEntries->at(i)->getFibEntry();
+  for (NameTree::const_iterator it = 
+    m_nameTree.fullEnumerate(&predicate_NameTreeEntry_hasFibEntry); it != m_nameTree.end(); it++)
+  {
+    shared_ptr<fib::Entry> entry = it->getFibEntry();
     entry->removeNextHop(face);
   }
 }
 
-
 } // namespace nfd
diff --git a/daemon/table/name-tree-entry.hpp b/daemon/table/name-tree-entry.hpp
index 1708dbf..cca1908 100644
--- a/daemon/table/name-tree-entry.hpp
+++ b/daemon/table/name-tree-entry.hpp
@@ -21,12 +21,12 @@
 
 namespace name_tree {
 
-// Forward declaration
+// Forward declarations
 class Node;
 class Entry;
 
 /**
- * @brief Name Tree Node Class
+ * \brief Name Tree Node Class
  */
 class Node
 {
@@ -43,9 +43,9 @@
 };
 
 /**
- * @brief Name Tree Entry Class
+ * \brief Name Tree Entry Class
  */
-class Entry
+class Entry : noncopyable
 {
   // Make private members accessible by Name Tree
   friend class nfd::NameTree;
@@ -72,7 +72,10 @@
 
   std::vector<shared_ptr<Entry> >&
   getChildren();
-  
+
+  bool
+  hasChildren() const;
+
   bool
   isEmpty() const;
 
@@ -88,12 +91,15 @@
   void
   insertPitEntry(shared_ptr<pit::Entry> pit);
 
+  bool
+  hasPitEntries() const;
+
   std::vector<shared_ptr<pit::Entry> >&
   getPitEntries();
 
   /**
-   * @brief Erase a PIT Entry
-   * @details The address of this PIT Entry is required
+   * \brief Erase a PIT Entry
+   * \details The address of this PIT Entry is required
    */
   bool
   erasePitEntry(shared_ptr<pit::Entry> pit);
@@ -152,6 +158,12 @@
 }
 
 inline bool
+Entry::hasChildren() const
+{
+  return !m_children.empty();
+}
+
+inline bool
 Entry::isEmpty() const
 {
   return m_children.empty() &&
@@ -166,6 +178,12 @@
   return m_fibEntry;
 }
 
+inline bool
+Entry::hasPitEntries() const
+{
+  return !m_pitEntries.empty();
+}
+
 inline std::vector<shared_ptr<pit::Entry> >&
 Entry::getPitEntries()
 {
diff --git a/daemon/table/name-tree.cpp b/daemon/table/name-tree.cpp
index 964730e..5d11c27 100644
--- a/daemon/table/name-tree.cpp
+++ b/daemon/table/name-tree.cpp
@@ -38,6 +38,7 @@
   , m_nBuckets(nBuckets)
   , m_loadFactor(0.5)
   , m_resizeFactor(2)
+  , m_endIterator(FULL_ENUMERATE_TYPE, *this, m_end)
 {
   m_resizeThreshold = static_cast<size_t>(m_loadFactor *
                                           static_cast<double>(m_nBuckets));
@@ -186,7 +187,7 @@
 // Return the longest matching Entry address
 // start from the full name, and then remove 1 name comp each time
 shared_ptr<name_tree::Entry>
-NameTree::findLongestPrefixMatch(const Name& prefix, const name_tree::EntrySelector& entrySelector)
+NameTree::findLongestPrefixMatch(const Name& prefix, const name_tree::EntrySelector& entrySelector) const
 {
   NFD_LOG_DEBUG("findLongestPrefixMatch " << prefix);
 
@@ -274,63 +275,82 @@
   return false; // if this entry is not empty
 }
 
-shared_ptr<std::vector<shared_ptr<name_tree::Entry> > >
-NameTree::fullEnumerate(const name_tree::EntrySelector& entrySelector)
+NameTree::const_iterator
+NameTree::fullEnumerate(const name_tree::EntrySelector& entrySelector) const
 {
   NFD_LOG_DEBUG("fullEnumerate");
 
-  shared_ptr<std::vector<shared_ptr<name_tree::Entry> > > results =
-    make_shared<std::vector<shared_ptr<name_tree::Entry> > >();
-
-  for (size_t i = 0; i < m_nBuckets; i++) {
-    for (name_tree::Node* node = m_buckets[i]; node != 0; node = node->m_next) {
-      if (static_cast<bool>(node->m_entry) && entrySelector(*node->m_entry)) {
-        results->push_back(node->m_entry);
-      }
-    }
-  }
-
-  return results;
-}
-
-// Helper function for partialEnumerate()
-void
-NameTree::partialEnumerateAddChildren(shared_ptr<name_tree::Entry> entry,
-                                      const name_tree::EntrySelector& entrySelector,
-                                      std::vector<shared_ptr<name_tree::Entry> >& results)
-{
-  BOOST_ASSERT(static_cast<bool>(entry));
-  
-  if (!entrySelector(*entry)) {
-    return;
-  }
-
-  results.push_back(entry);
-  for (size_t i = 0; i < entry->m_children.size(); i++)
+  // find the first eligible entry
+  for (size_t i = 0; i < m_nBuckets; i++)
     {
-      shared_ptr<name_tree::Entry> child = entry->m_children[i];
-      partialEnumerateAddChildren(child, entrySelector, results);
+      for (name_tree::Node* node = m_buckets[i]; node != 0; node = node->m_next)
+        {
+          if (static_cast<bool>(node->m_entry) && entrySelector(*node->m_entry))
+            {
+              const_iterator it(FULL_ENUMERATE_TYPE, *this, node->m_entry, entrySelector);
+              return it;
+            }
+        }
+    }
+
+  // If none of the entry satisfies the requirements, then return the end() iterator.
+  return end();
+}
+
+NameTree::const_iterator
+NameTree::partialEnumerate(const Name& prefix,
+                           const name_tree::EntrySubTreeSelector& entrySubTreeSelector) const
+{
+  // the first step is to process the root node
+  shared_ptr<name_tree::Entry> entry = findExactMatch(prefix);
+  if (!static_cast<bool>(entry))
+    {
+      return end();
+    }
+
+  std::pair<bool, bool>result = entrySubTreeSelector(*entry);
+  const_iterator it(PARTIAL_ENUMERATE_TYPE,
+                    *this,
+                    entry,
+                    name_tree::AnyEntry(),
+                    entrySubTreeSelector);
+
+  it.m_shouldVisitChildren = (result.second && entry->hasChildren());
+
+  if (result.first)
+    {
+      // root node is acceptable
+      return it;
+    }
+  else
+    {
+      // let the ++ operator handle it
+      ++it;
+      return it;
     }
 }
 
-shared_ptr<std::vector<shared_ptr<name_tree::Entry> > >
-NameTree::partialEnumerate(const Name& prefix,
-                           const name_tree::EntrySelector& entrySelector)
+NameTree::const_iterator
+NameTree::findAllMatches(const Name& prefix,
+                         const name_tree::EntrySelector& entrySelector) const
 {
-  NFD_LOG_DEBUG("partialEnumerate" << prefix);
+  NFD_LOG_DEBUG("NameTree::findAllMatches" << prefix);
 
-  shared_ptr<std::vector<shared_ptr<name_tree::Entry> > > results =
-    make_shared<std::vector<shared_ptr<name_tree::Entry> > >();
+  // As we are using Name Prefix Hash Table, and the current LPM() is
+  // implemented as starting from full name, and reduce the number of
+  // components by 1 each time, we could use it here.
+  // For trie-like design, it could be more efficient by walking down the
+  // trie from the root node.
 
-  // find the hash bucket corresponding to that prefix
-  shared_ptr<name_tree::Entry> entry = findExactMatch(prefix);
+  shared_ptr<name_tree::Entry> entry = findLongestPrefixMatch(prefix, entrySelector);
 
-  if (static_cast<bool>(entry)) {
-    // go through its children list via depth-first-search
-    partialEnumerateAddChildren(entry, entrySelector, *results);
-  }
-
-  return results;
+  if (static_cast<bool>(entry))
+    {
+      const_iterator it(FIND_ALL_MATCHES_TYPE, *this, entry, entrySelector);
+      return it;
+    }
+  // If none of the entry satisfies the requirements, then return the end() iterator.
+  return end();
 }
 
 // Hash Table Resize
@@ -388,7 +408,7 @@
 
 // For debugging
 void
-NameTree::dump(std::ostream& output)
+NameTree::dump(std::ostream& output) const
 {
   NFD_LOG_DEBUG("dump()");
 
@@ -440,4 +460,183 @@
   output << "--------------------------\n";
 }
 
+NameTree::const_iterator::const_iterator(NameTree::IteratorType type,
+                            const NameTree& nameTree,
+                            shared_ptr<name_tree::Entry> entry,
+                            const name_tree::EntrySelector& entrySelector,
+                            const name_tree::EntrySubTreeSelector& entrySubTreeSelector)
+  : m_nameTree(nameTree)
+  , m_entry(entry)
+  , m_subTreeRoot(entry)
+  , m_entrySelector(make_shared<name_tree::EntrySelector>(entrySelector))
+  , m_entrySubTreeSelector(make_shared<name_tree::EntrySubTreeSelector>(entrySubTreeSelector))
+  , m_type(type)
+  , m_shouldVisitChildren(true)
+{
+}
+
+// operator++()
+NameTree::const_iterator
+NameTree::const_iterator::operator++()
+{
+  NFD_LOG_DEBUG("const_iterator::operator++()");
+
+  BOOST_ASSERT(m_entry != m_nameTree.m_end);
+
+  if (m_type == FULL_ENUMERATE_TYPE) // fullEnumerate
+    {
+      bool isFound = false;
+      // process the entries in the same bucket first
+      while (m_entry->m_node->m_next != 0)
+        {
+          m_entry = m_entry->m_node->m_next->m_entry;
+          if ((*m_entrySelector)(*m_entry))
+            {
+              isFound = true;
+              return *this;
+            }
+        }
+
+      // process other buckets
+      int newLocation = m_entry->m_hash % m_nameTree.m_nBuckets + 1;
+      for (newLocation = newLocation; newLocation < m_nameTree.m_nBuckets; newLocation++)
+        {
+          // process each bucket
+          name_tree::Node* node = m_nameTree.m_buckets[newLocation];
+          while (node != 0)
+            {
+              m_entry = node->m_entry;
+              if ((*m_entrySelector)(*m_entry))
+                {
+                  isFound = true;
+                  return *this;
+                }
+              node = node->m_next;
+            }
+        }
+      BOOST_ASSERT(isFound == false);
+      // Reach to the end()
+      m_entry = m_nameTree.m_end;
+      return *this;
+    }
+
+  if (m_type == PARTIAL_ENUMERATE_TYPE) // partialEnumerate
+    {
+      // We use pre-order traversal.
+      // if at the root, it could have already been accepted, or this
+      // iterator was just declared, and root doesn't satisfy the
+      // requirement
+      // The if() section handles this special case
+      // Essentially, we need to check root's fist child, and the rest will
+      // be the same as normal process
+      if (m_entry == m_subTreeRoot)
+        {
+          if (m_shouldVisitChildren)
+            {
+              m_entry = m_entry->getChildren()[0];
+              std::pair<bool, bool> result = ((*m_entrySubTreeSelector)(*m_entry));
+              m_shouldVisitChildren = (result.second && m_entry->hasChildren());
+              if(result.first)
+                {
+                  return *this;
+                }
+              else
+                {
+                  // the first child did not meet the requirement
+                  // the rest of the process can just fall through the while loop
+                  // as normal
+                }
+            }
+          else
+            {
+              // no children, should return end();
+              // just fall through
+            }
+        }
+
+      // The first thing to do is to visit its child, or go to find its possible
+      // siblings
+      while (m_entry != m_subTreeRoot)
+        {
+          if (m_shouldVisitChildren)
+            {
+              // If this subtree should be visited
+              m_entry = m_entry->getChildren()[0];
+              std::pair<bool, bool> result = ((*m_entrySubTreeSelector)(*m_entry));
+              m_shouldVisitChildren = (result.second && m_entry->hasChildren());
+              if (result.first) // if this node is acceptable
+                {
+                  return *this;
+                }
+              else
+                {
+                  // do nothing, as this node is essentially ignored
+                  // send this node to the while loop.
+                }
+            }
+          else
+            {
+              // Should try to find its sibling
+              shared_ptr<name_tree::Entry> parent = m_entry->getParent();
+
+              std::vector<shared_ptr<name_tree::Entry> >& parentChildrenList = parent->getChildren();
+              bool isFound = false;
+              size_t i = 0;
+              for (i = 0; i < parentChildrenList.size(); i++)
+                {
+                  if (parentChildrenList[i] == m_entry)
+                    {
+                      isFound = true;
+                      break;
+                    }
+                }
+
+              BOOST_ASSERT(isFound == true);
+              if (i < parentChildrenList.size() - 1) // m_entry not the last child
+                {
+                  m_entry = parentChildrenList[i + 1];
+                  std::pair<bool, bool> result = ((*m_entrySubTreeSelector)(*m_entry));
+                  m_shouldVisitChildren = (result.second && m_entry->hasChildren());
+                  if (result.first) // if this node is acceptable
+                    {
+                      return *this;
+                    }
+                  else
+                    {
+                      // do nothing, as this node is essentially ignored
+                      // send this node to the while loop.
+                    }
+                }
+              else
+                {
+                  // m_entry is the last child, no more sibling, should try to find parent's sibling
+                  m_shouldVisitChildren = false;
+                  m_entry = parent;
+                }
+            }
+        }
+
+      m_entry = m_nameTree.m_end;
+      return *this;
+    }
+
+  if (m_type == FIND_ALL_MATCHES_TYPE) // findAllMatches
+    {
+      // Assumption: at the beginning, m_entry was initialized with the first
+      // eligible Name Tree entry (i.e., has a PIT entry that can be satisfied
+      // by the Data packet)
+
+      while (static_cast<bool>(m_entry->getParent()))
+        {
+          m_entry = m_entry->getParent();
+          if ((*m_entrySelector)(*m_entry))
+            return *this;
+        }
+
+      // Reach to the end (Root)
+      m_entry = m_nameTree.m_end;
+      return *this;
+    }
+}
+
 } // namespace nfd
diff --git a/daemon/table/name-tree.hpp b/daemon/table/name-tree.hpp
index 812c916..1a30b2b 100644
--- a/daemon/table/name-tree.hpp
+++ b/daemon/table/name-tree.hpp
@@ -16,8 +16,8 @@
 namespace name_tree {
 
 /**
- * @brief Compute the hash value of the given name prefix.
- * @todo 1) have another parameter that specifies the number of components
+ * \brief Compute the hash value of the given name prefix.
+ * \todo 1) have another parameter that specifies the number of components
  * 2) optimize the hash function to return a list of have values for all
  * the (or a certain number of, like a batch operation) prefixes. 3) move
  * the hash-related code to a separate file in /core or ndn-cpp-dev lib.
@@ -28,6 +28,13 @@
 /// a predicate to accept or reject an Entry in find operations
 typedef function<bool (const Entry& entry)> EntrySelector;
 
+/**
+ * \brief a predicate to accept or reject an Entry and its children
+ * \return .first indicates whether entry should be accepted;
+ *         .second indicates whether entry's children should be visited
+ */
+typedef function<std::pair<bool,bool> (const Entry& entry)> EntrySubTreeSelector;
+
 struct AnyEntry {
   bool
   operator()(const Entry& entry)
@@ -36,134 +43,201 @@
   }
 };
 
+struct AnyEntrySubTree {
+  std::pair<bool, bool>
+  operator()(const Entry& entry)
+  {
+    return std::make_pair(true, true);
+  }
+};
+
 } // namespace name_tree
 
 /**
- * @brief Class Name Tree
+ * \brief Class Name Tree
  */
 class NameTree : noncopyable
 {
 public:
+  class const_iterator;
+
   explicit
   NameTree(size_t nBuckets);
 
   ~NameTree();
 
   /**
-   * @brief Get the number of occupied entries in the Name Tree
+   * \brief Get the number of occupied entries in the Name Tree
    */
   size_t
   size() const;
 
   /**
-   * @brief Get the number of buckets in the Name Tree (NPHT)
-   * @details The number of buckets is the one that used to create the hash
+   * \brief Get the number of buckets in the Name Tree (NPHT)
+   * \details The number of buckets is the one that used to create the hash
    * table, i.e., m_nBuckets.
    */
   size_t
   getNBuckets() const;
 
   /**
-   * @brief Look for the Name Tree Entry that contains this name prefix.
-   * @details Starts from the shortest name prefix, and then increase the
+   * \brief Look for the Name Tree Entry that contains this name prefix.
+   * \details Starts from the shortest name prefix, and then increase the
    * number of name components by one each time. All non-existing Name Tree
    * Entries will be created.
-   * @param prefix The querying name prefix.
-   * @return The pointer to the Name Tree Entry that contains this full name
+   * \param prefix The querying name prefix.
+   * \return The pointer to the Name Tree Entry that contains this full name
    * prefix.
    */
   shared_ptr<name_tree::Entry>
   lookup(const Name& prefix);
 
   /**
-   * @brief Exact match lookup for the given name prefix.
-   * @return a null shared_ptr if this prefix is not found;
+   * \brief Exact match lookup for the given name prefix.
+   * \return a null shared_ptr if this prefix is not found;
    * otherwise return the Name Tree Entry address
    */
   shared_ptr<name_tree::Entry>
   findExactMatch(const Name& prefix) const;
 
   /**
-   * @brief Erase a Name Tree Entry if this entry is empty.
-   * @details If a Name Tree Entry contains no Children, no FIB, no PIT, and
+   * \brief Erase a Name Tree Entry if this entry is empty.
+   * \details If a Name Tree Entry contains no Children, no FIB, no PIT, and
    * no Measurements entries, then it can be erased. In addition, its parent entry
    * will also be examined by following the parent pointer until all empty entries
    * are erased.
-   * @param entry The pointer to the entry to be erased. The entry pointer should
+   * \param entry The pointer to the entry to be erased. The entry pointer should
    * returned by the findExactMatch(), lookup(), or findLongestPrefixMatch() functions.
    */
   bool
   eraseEntryIfEmpty(shared_ptr<name_tree::Entry> entry);
 
   /**
-   * @brief Longest prefix matching for the given name
-   * @details Starts from the full name string, reduce the number of name component
+   * \brief Longest prefix matching for the given name
+   * \details Starts from the full name string, reduce the number of name component
    * by one each time, until an Entry is found.
    */
   shared_ptr<name_tree::Entry>
   findLongestPrefixMatch(const Name& prefix,
-                         const name_tree::EntrySelector& entrySelector = name_tree::AnyEntry());
+                         const name_tree::EntrySelector& entrySelector =
+                         name_tree::AnyEntry()) const;
 
   /**
-   * @brief Resize the hash table size when its load factor reaches a threshold.
-   * @details As we are currently using a hand-written hash table implementation
+   * \brief Resize the hash table size when its load factor reaches a threshold.
+   * \details As we are currently using a hand-written hash table implementation
    * for the Name Tree, the hash table resize() function should be kept in the
    * name-tree.hpp file.
-   * @param newNBuckets The number of buckets for the new hash table.
+   * \param newNBuckets The number of buckets for the new hash table.
    */
   void
   resize(size_t newNBuckets);
 
   /**
-   * @brief Enumerate all the name prefixes stored in the Name Tree.
+   * \brief Enumerate all the name prefixes stored in the Name Tree.
    */
-  shared_ptr<std::vector<shared_ptr<name_tree::Entry> > >
-  fullEnumerate(const name_tree::EntrySelector& entrySelector = name_tree::AnyEntry());
+  const_iterator
+  fullEnumerate(const name_tree::EntrySelector& entrySelector = name_tree::AnyEntry()) const;
 
   /**
-   * @brief Enumerate all the name prefixes under a specific name prefix
-   * @todo It might be better to have functions like fullEnemerateFib() to reduce the
-   * number of entries stored in the vector.
-   */
-  shared_ptr<std::vector<shared_ptr<name_tree::Entry> > >
+   * \brief Enumerate all the name prefixes that satisfies the EntrySubTreeSelector.
+  */
+  const_iterator
   partialEnumerate(const Name& prefix,
-                   const name_tree::EntrySelector& entrySelector = name_tree::AnyEntry());
+                   const name_tree::EntrySubTreeSelector& entrySubTreeSelector = name_tree::AnyEntrySubTree()) const;
 
   /**
-   * @brief Dump all the information stored in the Name Tree for debugging.
+   * \brief Enumerate all the name prefixes that satisfy the prefix and entrySelector
+   */
+  const_iterator
+  findAllMatches(const Name& prefix,
+                 const name_tree::EntrySelector& entrySelector = name_tree::AnyEntry()) const;
+
+  /**
+   * \brief Dump all the information stored in the Name Tree for debugging.
    */
   void
-  dump(std::ostream& output);
+  dump(std::ostream& output) const;
+
+  const_iterator
+  begin() const;
+
+  const_iterator
+  end() const;
+
+  enum IteratorType
+  {
+    FULL_ENUMERATE_TYPE,
+    PARTIAL_ENUMERATE_TYPE,
+    FIND_ALL_MATCHES_TYPE
+  };
+
+  class const_iterator : public std::iterator<std::forward_iterator_tag, name_tree::Entry>
+  {
+  public:
+    friend class NameTree;
+
+    const_iterator(NameTree::IteratorType type,
+      const NameTree& nameTree,
+      shared_ptr<name_tree::Entry> entry,
+      const name_tree::EntrySelector& entrySelector = name_tree::AnyEntry(),
+      const name_tree::EntrySubTreeSelector& entrySubTreeSelector = name_tree::AnyEntrySubTree());
+
+    ~const_iterator();
+
+    const name_tree::Entry&
+    operator*() const;
+
+    shared_ptr<name_tree::Entry>
+    operator->() const;
+
+    const_iterator
+    operator++();
+
+    const_iterator
+    operator++(int);
+
+    bool
+    operator==(const const_iterator& other) const;
+
+    bool
+    operator!=(const const_iterator& other) const;
+
+  private:
+    bool                                        m_shouldVisitChildren;
+    const NameTree&                             m_nameTree;
+    shared_ptr<name_tree::Entry>                m_entry;
+    shared_ptr<name_tree::Entry>                m_subTreeRoot;
+    shared_ptr<name_tree::EntrySelector>        m_entrySelector;
+    shared_ptr<name_tree::EntrySubTreeSelector> m_entrySubTreeSelector;
+    NameTree::IteratorType                      m_type;
+  };
 
 private:
-  size_t m_nItems;  // Number of items being stored
-  size_t m_nBuckets; // Number of hash buckets
-  double m_loadFactor;
-  size_t m_resizeThreshold;
-  int m_resizeFactor;
-  name_tree::Node** m_buckets; // Name Tree Buckets in the NPHT
+  size_t                        m_nItems;  // Number of items being stored
+  size_t                        m_nBuckets; // Number of hash buckets
+  double                        m_loadFactor;
+  size_t                        m_resizeThreshold;
+  int                           m_resizeFactor;
+  name_tree::Node**             m_buckets; // Name Tree Buckets in the NPHT
+  shared_ptr<name_tree::Entry>  m_end;
+  const_iterator                m_endIterator;
 
   /**
-   * @brief Create a Name Tree Entry if it does not exist, or return the existing
+   * \brief Create a Name Tree Entry if it does not exist, or return the existing
    * Name Tree Entry address.
-   * @details Called by lookup() only.
-   * @return The first item is the Name Tree Entry address, the second item is
+   * \details Called by lookup() only.
+   * \return The first item is the Name Tree Entry address, the second item is
    * a bool value indicates whether this is an old entry (false) or a new
    * entry (true).
    */
   std::pair<shared_ptr<name_tree::Entry>, bool>
   insert(const Name& prefix);
-
-  /**
-   * @brief Helper function for partialEnumerate()
-   */
-  void
-  partialEnumerateAddChildren(shared_ptr<name_tree::Entry> entry,
-                              const name_tree::EntrySelector& entrySelector,
-                              std::vector<shared_ptr<name_tree::Entry> >& results);
-
 };
 
+inline NameTree::const_iterator::~const_iterator()
+{
+}
+
 inline size_t
 NameTree::size() const
 {
@@ -176,6 +250,50 @@
   return m_nBuckets;
 }
 
+inline NameTree::const_iterator
+NameTree::begin() const
+{
+  return fullEnumerate();
+}
+
+inline NameTree::const_iterator
+NameTree::end() const
+{
+  return m_endIterator;
+}
+
+inline const name_tree::Entry&
+NameTree::const_iterator::operator*() const
+{
+  return *m_entry;
+}
+
+inline shared_ptr<name_tree::Entry>
+NameTree::const_iterator::operator->() const
+{
+  return m_entry;
+}
+
+inline NameTree::const_iterator
+NameTree::const_iterator::operator++(int)
+{
+  NameTree::const_iterator temp(*this);
+  ++(*this);
+  return temp;
+}
+
+inline bool
+NameTree::const_iterator::operator==(const NameTree::const_iterator& other) const
+{
+  return m_entry == other.m_entry;
+}
+
+inline bool
+NameTree::const_iterator::operator!=(const NameTree::const_iterator& other) const
+{
+  return m_entry != other.m_entry;
+}
+
 } // namespace nfd
 
 #endif // NFD_TABLE_NAME_TREE_HPP
diff --git a/daemon/table/pit.cpp b/daemon/table/pit.cpp
index 6f5acf3..dafec47 100644
--- a/daemon/table/pit.cpp
+++ b/daemon/table/pit.cpp
@@ -4,19 +4,6 @@
  * See COPYING for copyright and distribution information.
  */
 
-/**
- *  KNOWN ISSUES
- *  
- *  - To remove a PIT entry, we need to first perform a lookup on NameTree
- *  to locate its NameTree Entry, and then call NameTreeEntry->deletePitEntry()
- *  function. Alternatively, we could store a pointer at each PIT-Entry, which
- *  would speed up this procedure with the cost of additional memory space. Maybe
- *  this could also be part of the PIT/FIB/Measurement shortcut, where all of these
- *  entries have pointers to their NameTreeEntry. Which could be part of task
- *  #1202, shortcuts between FIB, PIT, Measurements.
- *  
- */
-
 #include "pit.hpp"
 
 namespace nfd {
@@ -30,6 +17,12 @@
 }
 
 static inline bool
+predicate_NameTreeEntry_hasPitEntry(const name_tree::Entry& entry)
+{
+  return entry.hasPitEntries();
+}
+
+static inline bool
 operator==(const Exclude& a, const Exclude& b)
 {
   const Block& aBlock = a.wireEncode();
@@ -57,10 +50,10 @@
 {
   // - first lookup() the Interest Name in the NameTree, which will creates all
   // the intermedia nodes, starting from the shortest prefix.
-  // - if it is guaranteed that this Interest already has a NameTree Entry, we 
+  // - if it is guaranteed that this Interest already has a NameTree Entry, we
   // could use findExactMatch() instead.
-  // - Alternatively, we could try to do findExactMatch() first, if not found, then 
-  // do lookup().
+  // - Alternatively, we could try to do findExactMatch() first, if not found,
+  // then do lookup().
   shared_ptr<name_tree::Entry> nameTreeEntry = m_nameTree.lookup(interest.getName());
 
   BOOST_ASSERT(static_cast<bool>(nameTreeEntry));
@@ -91,19 +84,11 @@
 {
   shared_ptr<pit::DataMatchResult> result = make_shared<pit::DataMatchResult>();
 
-  shared_ptr<name_tree::Entry> nameTreeEntry;
-
-  // NOTE: We are using findLongestPrefixMatch() here.
-  // The reason is that findLongestPrefixMatch() starts with the full name
-  // and then remove one component each time, which is the type of behavior we would like
-  // to use here.
-  // If it could be guranteed that the quering Data packet always has a Name Tree
-  // Entry, we could also use findExactMatch(). 
-  for (nameTreeEntry = m_nameTree.findLongestPrefixMatch(data.getName()); 
-                                   static_cast<bool>(nameTreeEntry);
-                                   nameTreeEntry = nameTreeEntry->getParent())
+  for (NameTree::const_iterator it =
+       m_nameTree.findAllMatches(data.getName(), &predicate_NameTreeEntry_hasPitEntry);
+       it != m_nameTree.end(); it++)
     {
-      std::vector<shared_ptr<pit::Entry> >& pitEntries = nameTreeEntry->getPitEntries();
+      std::vector<shared_ptr<pit::Entry> >& pitEntries = it->getPitEntries();
       for (size_t i = 0; i < pitEntries.size(); i++)
         {
           if (pitEntries[i]->getInterest().matchesName(data.getName()))
@@ -125,7 +110,7 @@
   BOOST_ASSERT(static_cast<bool>(nameTreeEntry));
 
   // erase this PIT entry
-  if (static_cast<bool>(nameTreeEntry)) 
+  if (static_cast<bool>(nameTreeEntry))
     {
       nameTreeEntry->erasePitEntry(pitEntry);
       m_nameTree.eraseEntryIfEmpty(nameTreeEntry);
diff --git a/daemon/table/pit.hpp b/daemon/table/pit.hpp
index 9ea5aac..e0b5ba2 100644
--- a/daemon/table/pit.hpp
+++ b/daemon/table/pit.hpp
@@ -31,31 +31,31 @@
 public:
   explicit
   Pit(NameTree& nameTree);
-   
+
   ~Pit();
 
-  /** 
+  /**
    *  \brief Get the number of items stored in the PIT.
    */
-  size_t 
+  size_t
   size() const;
-  
+
   /** \brief inserts a FIB entry for prefix
    *  If an entry for exact same prefix exists, that entry is returned.
    *  \return{ the entry, and true for new entry, false for existing entry }
    */
   std::pair<shared_ptr<pit::Entry>, bool>
   insert(const Interest& interest);
-  
+
   /** \brief performs a Data match
    *  \return{ an iterable of all PIT entries matching data }
    */
   shared_ptr<pit::DataMatchResult>
   findAllDataMatches(const Data& data) const;
-    
+
   /**
    *  \brief Erase a PIT Entry
-   */  
+   */
   void
   erase(shared_ptr<pit::Entry> pitEntry);
 
diff --git a/tests/table/name-tree.cpp b/tests/table/name-tree.cpp
index 4411fd2..e44c401 100644
--- a/tests/table/name-tree.cpp
+++ b/tests/table/name-tree.cpp
@@ -5,7 +5,6 @@
  */
 
 #include "table/name-tree.hpp"
-
 #include "tests/test-common.hpp"
 
 namespace nfd {
@@ -19,7 +18,7 @@
 {
   Name prefix("ndn:/named-data/research/abc/def/ghi");
 
-  name_tree::Entry npe = name_tree::Entry(prefix);
+  name_tree::Entry npe(prefix);
   BOOST_CHECK_EQUAL(npe.getPrefix(), prefix);
 
   // examine all the get methods
@@ -39,7 +38,7 @@
   std::vector< shared_ptr<pit::Entry> >& pitList = npe.getPitEntries();
   BOOST_CHECK_EQUAL(pitList.size(), 0);
 
-  // examine all the set method 
+  // examine all the set method
 
   npe.setHash(12345);
   BOOST_CHECK_EQUAL(npe.getHash(), 12345);
@@ -49,15 +48,15 @@
   npe.setParent(parent);
   BOOST_CHECK_EQUAL(npe.getParent(), parent);
 
-  // Insert FIB 
+  // Insert FIB
 
   shared_ptr<fib::Entry> fibEntry(new fib::Entry(prefix));
   shared_ptr<fib::Entry> fibEntryParent(new fib::Entry(parentName));
-  
+
   npe.setFibEntry(fibEntry);
   BOOST_CHECK_EQUAL(npe.getFibEntry(), fibEntry);
 
-  // Erase a FIB that does not exist 
+  // Erase a FIB that does not exist
   BOOST_CHECK_EQUAL(npe.
   eraseFibEntry(fibEntryParent), false);
   BOOST_CHECK_EQUAL(npe.getFibEntry(), fibEntry);
@@ -70,7 +69,7 @@
   // Insert a PIT
 
   shared_ptr<pit::Entry> PitEntry(make_shared<pit::Entry>(prefix));
-  shared_ptr<pit::Entry> PitEntry2(make_shared<pit::Entry>(parentName)); 
+  shared_ptr<pit::Entry> PitEntry2(make_shared<pit::Entry>(parentName));
 
   Name prefix3("ndn:/named-data/research/abc/def");
   shared_ptr<pit::Entry> PitEntry3(make_shared<pit::Entry>(prefix3));
@@ -107,25 +106,25 @@
   NameTree nt(nBuckets);
 
   BOOST_CHECK_EQUAL(nt.size(), 0);
-  BOOST_CHECK_EQUAL(nt.getNBuckets(), nBuckets); 
+  BOOST_CHECK_EQUAL(nt.getNBuckets(), nBuckets);
 
-  Name nameABC = ("ndn:/a/b/c");
+  Name nameABC("ndn:/a/b/c");
   shared_ptr<name_tree::Entry> npeABC = nt.lookup(nameABC);
   BOOST_CHECK_EQUAL(nt.size(), 4);
-  
-  Name nameABD = ("/a/b/d");
+
+  Name nameABD("/a/b/d");
   shared_ptr<name_tree::Entry> npeABD = nt.lookup(nameABD);
   BOOST_CHECK_EQUAL(nt.size(), 5);
 
-  Name nameAE = ("/a/e/");
+  Name nameAE("/a/e/");
   shared_ptr<name_tree::Entry> npeAE = nt.lookup(nameAE);
   BOOST_CHECK_EQUAL(nt.size(), 6);
 
-  Name nameF = ("/f");
+  Name nameF("/f");
   shared_ptr<name_tree::Entry> npeF = nt.lookup(nameF);
   BOOST_CHECK_EQUAL(nt.size(), 7);
 
-  // validate lookup() and findExactMatch() 
+  // validate lookup() and findExactMatch()
 
   Name nameAB ("/a/b");
   BOOST_CHECK_EQUAL(npeABC->getParent(), nt.findExactMatch(nameAB));
@@ -138,7 +137,7 @@
   BOOST_CHECK_EQUAL(npeF->getParent(), nt.findExactMatch(nameRoot));
   BOOST_CHECK_EQUAL(nt.size(), 7);
 
-  Name name0 = ("/does/not/exist");
+  Name name0("/does/not/exist");
   shared_ptr<name_tree::Entry> npe0 = nt.findExactMatch(name0);
   BOOST_CHECK(!static_cast<bool>(npe0));
 
@@ -174,8 +173,6 @@
   temp = nt.findLongestPrefixMatch(nameRootLPM);
   BOOST_CHECK_EQUAL(temp, nt.findExactMatch(nameRoot));
 
-  // nt.dump(std::cout);
-
   bool eraseResult = false;
   temp = nt.findExactMatch(nameABC);
   if (static_cast<bool>(temp))
@@ -187,7 +184,7 @@
 
   eraseResult = false;
   temp = nt.findExactMatch(nameABCLPM);
-  if (static_cast<bool>(temp)) 
+  if (static_cast<bool>(temp))
     eraseResult = nt.
   eraseEntryIfEmpty(temp);
   BOOST_CHECK(!static_cast<bool>(temp));
@@ -201,18 +198,16 @@
 
   eraseResult = false;
   temp = nt.findExactMatch(nameABC);
-  if (static_cast<bool>(temp)) 
+  if (static_cast<bool>(temp))
     eraseResult = nt.
   eraseEntryIfEmpty(temp);
   BOOST_CHECK_EQUAL(nt.size(), 6);
   BOOST_CHECK_EQUAL(eraseResult, true);
   BOOST_CHECK(!static_cast<bool>(nt.findExactMatch(nameABC)));
 
-  // nt.dump(std::cout);
-
   BOOST_CHECK_EQUAL(nt.getNBuckets(), 16);
 
-  // should resize now 
+  // should resize now
   Name nameABCD("a/b/c/d");
   nt.lookup(nameABCD);
   Name nameABCDE("a/b/c/d/e");
@@ -220,9 +215,7 @@
   BOOST_CHECK_EQUAL(nt.size(), 9);
   BOOST_CHECK_EQUAL(nt.getNBuckets(), 32);
 
-  // nt.dump(std::cout);
-
-  // try to erase /a/b/c, should return false 
+  // try to erase /a/b/c, should return false
   temp = nt.findExactMatch(nameABC);
   BOOST_CHECK_EQUAL(temp->getPrefix(), nameABC);
   eraseResult = nt.
@@ -232,38 +225,556 @@
   BOOST_CHECK_EQUAL(temp->getPrefix(), nameABC);
 
   temp = nt.findExactMatch(nameABD);
-  if (static_cast<bool>(temp)) 
+  if (static_cast<bool>(temp))
     nt.
   eraseEntryIfEmpty(temp);
   BOOST_CHECK_EQUAL(nt.size(), 8);
-  
-  // nt.dump(std::cout);
+}
 
-  shared_ptr<std::vector<shared_ptr<name_tree::Entry> > > fullList;
-  fullList = nt.fullEnumerate();
-  BOOST_CHECK_EQUAL(fullList->size(), 8);
-  // for (size_t j = 0; j < (*fullList).size(); j++)
-  // {
-  //  temp = (*fullList)[j];
-  //  std::cout << temp->getPrefix().toUri() << std::endl;
-  // }
+BOOST_AUTO_TEST_CASE(NameTreeIteratorFullEnumerate)
+{
+  using namespace std;
 
-  shared_ptr<std::vector<shared_ptr<name_tree::Entry> > > partialList;
-  partialList = nt.partialEnumerate(nameA);
-  BOOST_CHECK_EQUAL(partialList->size(), 6);
-  // for (size_t j = 0; j < (*partialList).size(); j++)
-  // {
-  //  temp = (*partialList)[j];
-  //  std::cout << temp->getPrefix().toUri() << std::endl;
-  // }
+  size_t nBuckets = 1024;
+  NameTree nt(nBuckets);
 
-  partialList = nt.partialEnumerate(nameRoot);
-  BOOST_CHECK_EQUAL(partialList->size(), 8);
-  // for (size_t j = 0; j < (*partialList).size(); j++)
-  // {
-  //  temp = (*partialList)[j];
-  //  std::cout << temp->getPrefix().toUri() << std::endl;
-  // }
+  BOOST_CHECK_EQUAL(nt.size(), 0);
+  BOOST_CHECK_EQUAL(nt.getNBuckets(), nBuckets);
+
+  Name nameABC("ndn:/a/b/c");
+  shared_ptr<name_tree::Entry> npeABC = nt.lookup(nameABC);
+  BOOST_CHECK_EQUAL(nt.size(), 4);
+
+  Name nameABD("/a/b/d");
+  shared_ptr<name_tree::Entry> npeABD = nt.lookup(nameABD);
+  BOOST_CHECK_EQUAL(nt.size(), 5);
+
+  Name nameAE("/a/e/");
+  shared_ptr<name_tree::Entry> npeAE = nt.lookup(nameAE);
+  BOOST_CHECK_EQUAL(nt.size(), 6);
+
+  Name nameF("/f");
+  shared_ptr<name_tree::Entry> npeF = nt.lookup(nameF);
+  BOOST_CHECK_EQUAL(nt.size(), 7);
+
+  Name nameRoot("/");
+  shared_ptr<name_tree::Entry> npeRoot = nt.lookup(nameRoot);
+  BOOST_CHECK_EQUAL(nt.size(), 7);
+
+  Name nameA("/a");
+  Name nameAB("/a/b");
+
+  bool hasRoot  = false;
+  bool hasA     = false;
+  bool hasAB    = false;
+  bool hasABC   = false;
+  bool hasABD   = false;
+  bool hasAE    = false;
+  bool hasF     = false;
+
+  int counter = 0;
+  NameTree::const_iterator it = nt.fullEnumerate();
+
+  for(; it != nt.end(); it++)
+  {
+    counter++;
+
+    if (it->getPrefix() == nameRoot)
+      hasRoot = true;
+    if (it->getPrefix() == nameA)
+      hasA    = true;
+    if (it->getPrefix() == nameAB)
+      hasAB   = true;
+    if (it->getPrefix() == nameABC)
+      hasABC  = true;
+    if (it->getPrefix() == nameABD)
+      hasABD  = true;
+    if (it->getPrefix() == nameAE)
+      hasAE   = true;
+    if (it->getPrefix() == nameF)
+      hasF    = true;
+  }
+
+  BOOST_CHECK_EQUAL(hasRoot , true);
+  BOOST_CHECK_EQUAL(hasA    , true);
+  BOOST_CHECK_EQUAL(hasAB   , true);
+  BOOST_CHECK_EQUAL(hasABC  , true);
+  BOOST_CHECK_EQUAL(hasABD  , true);
+  BOOST_CHECK_EQUAL(hasAE   , true);
+  BOOST_CHECK_EQUAL(hasF    , true);
+
+  BOOST_CHECK_EQUAL(counter , 7);
+}
+
+// Predicates for testing the partial enumerate function
+
+static inline std::pair<bool, bool>
+predicate_NameTreeEntry_NameA_Only(const name_tree::Entry& entry)
+{
+  Name nameA("/a");
+  bool first = nameA.equals(entry.getPrefix());
+  return std::make_pair(first, true);
+}
+
+static inline std::pair<bool, bool>
+predicate_NameTreeEntry_Except_NameA(const name_tree::Entry& entry)
+{
+  Name nameA("/a");
+  bool first = !(nameA.equals(entry.getPrefix()));
+  return std::make_pair(first, true);
+}
+
+static inline std::pair<bool, bool>
+predicate_NameTreeEntry_NoSubNameA(const name_tree::Entry& entry)
+{
+  Name nameA("/a");
+  bool second = !(nameA.equals(entry.getPrefix()));
+  return std::make_pair(true, second);
+}
+
+static inline std::pair<bool, bool>
+predicate_NameTreeEntry_NoNameA_NoSubNameAB(const name_tree::Entry& entry)
+{
+  Name nameA("/a");
+  Name nameAB("/a/b");
+  bool first = !(nameA.equals(entry.getPrefix()));
+  bool second = !(nameAB.equals(entry.getPrefix()));
+  return std::make_pair(first, second);
+}
+
+static inline std::pair<bool, bool>
+predicate_NameTreeEntry_NoNameA_NoSubNameAC(const name_tree::Entry& entry)
+{
+  Name nameA("/a");
+  Name nameAC("/a/c");
+  bool first = !(nameA.equals(entry.getPrefix()));
+  bool second = !(nameAC.equals(entry.getPrefix()));
+  return std::make_pair(first, second);
+}
+
+static inline std::pair<bool, bool>
+predicate_NameTreeEntry_Example(const name_tree::Entry& entry)
+{
+  Name nameRoot("/");
+  Name nameA("/a");
+  Name nameAB("/a/b");
+  Name nameABC("/a/b/c");
+  Name nameAD("/a/d");
+  Name nameE("/e");
+  Name nameF("/f");
+
+  bool first = false;
+  bool second = false;
+
+  Name name = entry.getPrefix();
+
+  if (name == nameRoot || name == nameAB || name == nameABC || name == nameAD)
+  {
+    first = true;
+  }
+
+  if(name == nameRoot || name == nameA || name == nameF)
+  {
+    second = true;
+  }
+
+  return std::make_pair(first, second);
+}
+
+BOOST_AUTO_TEST_CASE(NameTreeIteratorPartialEnumerate)
+{
+  using namespace std;
+  typedef NameTree::const_iterator const_iterator;
+
+  size_t nBuckets = 16;
+  NameTree nameTree(nBuckets);
+  int counter = 0;
+
+  // empty nameTree, should return end();
+  Name nameA("/a");
+  bool hasA = false;
+  const_iterator itA = nameTree.partialEnumerate(nameA);
+  BOOST_CHECK(itA == nameTree.end());
+
+  // We have "/", "/a", "/a/b", "a/c" now.
+  Name nameAB("/a/b");
+  bool hasAB = false;
+  nameTree.lookup(nameAB);
+
+  Name nameAC("/a/c");
+  bool hasAC = false;
+  nameTree.lookup(nameAC);
+  BOOST_CHECK_EQUAL(nameTree.size(), 4);
+
+  // Enumerate on some name that is not in nameTree
+  Name name0="/0";
+  const_iterator it0 = nameTree.partialEnumerate(name0);
+  BOOST_CHECK(it0 == nameTree.end());
+
+  // Accept "root" nameA only
+  const_iterator itAOnly = nameTree.partialEnumerate(nameA, &predicate_NameTreeEntry_NameA_Only);
+  BOOST_CHECK_EQUAL(itAOnly->getPrefix(), nameA);
+  BOOST_CHECK(++itAOnly == nameTree.end());
+
+  // Accept anything except "root" nameA
+  const_iterator itExceptA = nameTree.partialEnumerate(nameA, &predicate_NameTreeEntry_Except_NameA);
+  hasA = false;
+  hasAB = false;
+  hasAC = false;
+
+  counter = 0;
+  for (; itExceptA != nameTree.end(); itExceptA++)
+  {
+    counter++;
+
+    if (itExceptA->getPrefix() == nameA)
+      hasA  = true;
+
+    if (itExceptA->getPrefix() == nameAB)
+      hasAB = true;
+
+    if (itExceptA->getPrefix() == nameAC)
+      hasAC = true;
+  }
+  BOOST_CHECK_EQUAL(hasA,  false);
+  BOOST_CHECK_EQUAL(hasAB, true);
+  BOOST_CHECK_EQUAL(hasAC, true);
+
+  BOOST_CHECK_EQUAL(counter, 2);
+
+  Name nameAB1("a/b/1");
+  bool hasAB1 = false;
+  nameTree.lookup(nameAB1);
+
+  Name nameAB2("a/b/2");
+  bool hasAB2 = false;
+  nameTree.lookup(nameAB2);
+
+  Name nameAC1("a/c/1");
+  bool hasAC1 = false;
+  nameTree.lookup(nameAC1);
+
+  Name nameAC2("a/c/2");
+  bool hasAC2 = false;
+  nameTree.lookup(nameAC2);
+
+  BOOST_CHECK_EQUAL(nameTree.size(), 8);
+
+  // No NameA
+  // No SubTree from NameAB
+  const_iterator itNoNameANoSubNameAB = nameTree.partialEnumerate(nameA, &predicate_NameTreeEntry_NoNameA_NoSubNameAB);
+  hasA   = false;
+  hasAB  = false;
+  hasAB1 = false;
+  hasAB2 = false;
+  hasAC  = false;
+  hasAC1 = false;
+  hasAC2 = false;
+
+  counter = 0;
+
+  for (; itNoNameANoSubNameAB != nameTree.end(); itNoNameANoSubNameAB++)
+  {
+    counter++;
+
+    if (itNoNameANoSubNameAB->getPrefix() == nameA)
+      hasA   = true;
+
+    if (itNoNameANoSubNameAB->getPrefix() == nameAB)
+      hasAB  = true;
+
+    if (itNoNameANoSubNameAB->getPrefix() == nameAB1)
+      hasAB1 = true;
+
+    if (itNoNameANoSubNameAB->getPrefix() == nameAB2)
+      hasAB2 = true;
+
+    if (itNoNameANoSubNameAB->getPrefix() == nameAC)
+      hasAC  = true;
+
+    if (itNoNameANoSubNameAB->getPrefix() == nameAC1)
+      hasAC1 = true;
+
+    if (itNoNameANoSubNameAB->getPrefix() == nameAC2)
+      hasAC2 = true;
+  }
+
+  BOOST_CHECK_EQUAL(hasA,   false);
+  BOOST_CHECK_EQUAL(hasAB,  true);
+  BOOST_CHECK_EQUAL(hasAB1, false);
+  BOOST_CHECK_EQUAL(hasAB2, false);
+  BOOST_CHECK_EQUAL(hasAC,  true);
+  BOOST_CHECK_EQUAL(hasAC1, true);
+  BOOST_CHECK_EQUAL(hasAC2, true);
+
+  BOOST_CHECK_EQUAL(counter, 4);
+
+  // No NameA
+  // No SubTree from NameAC
+  const_iterator itNoNameANoSubNameAC = nameTree.partialEnumerate(nameA, &predicate_NameTreeEntry_NoNameA_NoSubNameAC);
+  hasA   = false;
+  hasAB  = false;
+  hasAB1 = false;
+  hasAB2 = false;
+  hasAC  = false;
+  hasAC1 = false;
+  hasAC2 = false;
+
+  counter = 0;
+
+  for (; itNoNameANoSubNameAC != nameTree.end(); itNoNameANoSubNameAC++)
+  {
+    counter++;
+
+    if (itNoNameANoSubNameAC->getPrefix() == nameA)
+      hasA   = true;
+
+    if (itNoNameANoSubNameAC->getPrefix() == nameAB)
+      hasAB  = true;
+
+    if (itNoNameANoSubNameAC->getPrefix() == nameAB1)
+      hasAB1 = true;
+
+    if (itNoNameANoSubNameAC->getPrefix() == nameAB2)
+      hasAB2 = true;
+
+    if (itNoNameANoSubNameAC->getPrefix() == nameAC)
+      hasAC  = true;
+
+    if (itNoNameANoSubNameAC->getPrefix() == nameAC1)
+      hasAC1 = true;
+
+    if (itNoNameANoSubNameAC->getPrefix() == nameAC2)
+      hasAC2 = true;
+  }
+
+  BOOST_CHECK_EQUAL(hasA,   false);
+  BOOST_CHECK_EQUAL(hasAB,  true);
+  BOOST_CHECK_EQUAL(hasAB1, true);
+  BOOST_CHECK_EQUAL(hasAB2, true);
+  BOOST_CHECK_EQUAL(hasAC,  true);
+  BOOST_CHECK_EQUAL(hasAC1, false);
+  BOOST_CHECK_EQUAL(hasAC2, false);
+
+  BOOST_CHECK_EQUAL(counter, 4);
+
+  // No Subtree from NameA
+  const_iterator itNoANoSubNameA = nameTree.partialEnumerate(nameA, &predicate_NameTreeEntry_NoSubNameA);
+
+  hasA   = false;
+  hasAB  = false;
+  hasAB1 = false;
+  hasAB2 = false;
+  hasAC  = false;
+  hasAC1 = false;
+  hasAC2 = false;
+
+  counter = 0;
+
+  for (; itNoANoSubNameA != nameTree.end(); itNoANoSubNameA++)
+  {
+    counter++;
+
+    if (itNoANoSubNameA->getPrefix() == nameA)
+      hasA   = true;
+
+    if (itNoANoSubNameA->getPrefix() == nameAB)
+      hasAB  = true;
+
+    if (itNoANoSubNameA->getPrefix() == nameAB1)
+      hasAB1 = true;
+
+    if (itNoANoSubNameA->getPrefix() == nameAB2)
+      hasAB2 = true;
+
+    if (itNoANoSubNameA->getPrefix() == nameAC)
+      hasAC  = true;
+
+    if (itNoANoSubNameA->getPrefix() == nameAC1)
+      hasAC1 = true;
+
+    if (itNoANoSubNameA->getPrefix() == nameAC2)
+      hasAC2 = true;
+  }
+
+  BOOST_CHECK_EQUAL(hasA,   true);
+  BOOST_CHECK_EQUAL(hasAB,  false);
+  BOOST_CHECK_EQUAL(hasAB1, false);
+  BOOST_CHECK_EQUAL(hasAB2, false);
+  BOOST_CHECK_EQUAL(hasAC,  false);
+  BOOST_CHECK_EQUAL(hasAC1, false);
+  BOOST_CHECK_EQUAL(hasAC2, false);
+
+  BOOST_CHECK_EQUAL(counter, 1);
+
+  // Example
+  // /
+  // /A
+  // /A/B x
+  // /A/B/C
+  // /A/D x
+  // /E
+  // /F
+
+  NameTree nameTreeExample(nBuckets);
+
+  Name nameRoot("/");
+  bool hasRoot = false;
+
+  nameTreeExample.lookup(nameA);
+  hasA = false;
+  nameTreeExample.lookup(nameAB);
+  hasAB = false;
+
+  Name nameABC("a/b/c");
+  bool hasABC = false;
+  nameTreeExample.lookup(nameABC);
+
+  Name nameAD("/a/d");
+  nameTreeExample.lookup(nameAD);
+  bool hasAD = false;
+
+  Name nameE("/e");
+  nameTreeExample.lookup(nameE);
+  bool hasE = false;
+
+  Name nameF("/f");
+  nameTreeExample.lookup(nameF);
+  bool hasF = false;
+
+  counter = 0;
+  const_iterator itExample = nameTreeExample.partialEnumerate(nameA, &predicate_NameTreeEntry_Example);
+
+  for (; itExample != nameTreeExample.end(); itExample++)
+  {
+    counter++;
+
+    if (itExample->getPrefix() == nameRoot)
+      hasRoot = true;
+
+    if (itExample->getPrefix() == nameA)
+     hasA     = true;
+
+    if (itExample->getPrefix() == nameAB)
+     hasAB    = true;
+
+    if (itExample->getPrefix() == nameABC)
+     hasABC   = true;
+
+    if (itExample->getPrefix() == nameAD)
+     hasAD    = true;
+
+    if (itExample->getPrefix() == nameE)
+     hasE     = true;
+
+    if (itExample->getPrefix() == nameF)
+      hasF    = true;
+  }
+
+  BOOST_CHECK_EQUAL(hasRoot, false);
+  BOOST_CHECK_EQUAL(hasA,    false);
+  BOOST_CHECK_EQUAL(hasAB,   true);
+  BOOST_CHECK_EQUAL(hasABC,  false);
+  BOOST_CHECK_EQUAL(hasAD,   true);
+  BOOST_CHECK_EQUAL(hasE,    false);
+  BOOST_CHECK_EQUAL(hasF,    false);
+
+  BOOST_CHECK_EQUAL(counter, 2);
+}
+
+
+BOOST_AUTO_TEST_CASE(NameTreeIteratorFindAllMatches)
+{
+  using namespace std;
+
+  size_t nBuckets = 16;
+  NameTree nt(nBuckets);
+  int counter = 0;
+
+  Name nameABCDEF("a/b/c/d/e/f");
+  shared_ptr<name_tree::Entry> npeABCDEF = nt.lookup(nameABCDEF);
+
+  Name nameAAC("a/a/c");
+  shared_ptr<name_tree::Entry> npeAAC = nt.lookup(nameAAC);
+
+  Name nameAAD1("a/a/d/1");
+  shared_ptr<name_tree::Entry> npeAAD1 = nt.lookup(nameAAD1);
+
+  Name nameAAD2("a/a/d/2");
+  shared_ptr<name_tree::Entry> npeAAD2 = nt.lookup(nameAAD2);
+
+
+  BOOST_CHECK_EQUAL(nt.size(), 12);
+
+  Name nameRoot ("/");
+  Name nameA    ("/a");
+  Name nameAB   ("/a/b");
+  Name nameABC  ("/a/b/c");
+  Name nameABCD ("/a/b/c/d");
+  Name nameABCDE("/a/b/c/d/e");
+  Name nameAA   ("/a/a");
+  Name nameAAD  ("/a/a/d");
+
+  bool hasRoot    = false;
+  bool hasA       = false;
+  bool hasAB      = false;
+  bool hasABC     = false;
+  bool hasABCD    = false;
+  bool hasABCDE   = false;
+  bool hasABCDEF  = false;
+  bool hasAA      = false;
+  bool hasAAC     = false;
+  bool hasAAD     = false;
+  bool hasAAD1    = false;
+  bool hasAAD2    = false;
+
+  counter = 0;
+
+  for (NameTree::const_iterator it = nt.findAllMatches(nameABCDEF);
+      it != nt.end(); it++)
+  {
+    counter++;
+
+    if (it->getPrefix() == nameRoot)
+      hasRoot   = true;
+    if (it->getPrefix() == nameA)
+      hasA      = true;
+    if (it->getPrefix() == nameAB)
+      hasAB     = true;
+    if (it->getPrefix() == nameABC)
+      hasABC    = true;
+    if (it->getPrefix() == nameABCD)
+      hasABCD   = true;
+    if (it->getPrefix() == nameABCDE)
+      hasABCDE  = true;
+    if (it->getPrefix() == nameABCDEF)
+      hasABCDEF = true;
+    if (it->getPrefix() == nameAA)
+      hasAA     = true;
+    if (it->getPrefix() == nameAAC)
+      hasAAC    = true;
+    if (it->getPrefix() == nameAAD)
+      hasAAD    = true;
+    if (it->getPrefix() == nameAAD1)
+      hasAAD1   = true;
+    if (it->getPrefix() == nameAAD2)
+      hasAAD2   = true;
+  }
+
+  BOOST_CHECK_EQUAL(hasRoot   , true);
+  BOOST_CHECK_EQUAL(hasA      , true);
+  BOOST_CHECK_EQUAL(hasAB     , true);
+  BOOST_CHECK_EQUAL(hasABC    , true);
+  BOOST_CHECK_EQUAL(hasABCD   , true);
+  BOOST_CHECK_EQUAL(hasABCDE  , true);
+  BOOST_CHECK_EQUAL(hasABCDEF , true);
+  BOOST_CHECK_EQUAL(hasAA     , false);
+  BOOST_CHECK_EQUAL(hasAAC    , false);
+  BOOST_CHECK_EQUAL(hasAAD    , false);
+  BOOST_CHECK_EQUAL(hasAAD1   , false);
+  BOOST_CHECK_EQUAL(hasAAD2   , false);
+
+  BOOST_CHECK_EQUAL(counter, 7);
 }
 
 BOOST_AUTO_TEST_SUITE_END()
diff --git a/tests/table/pit.cpp b/tests/table/pit.cpp
index f366ea2..5cece6a 100644
--- a/tests/table/pit.cpp
+++ b/tests/table/pit.cpp
@@ -241,50 +241,63 @@
 
 BOOST_AUTO_TEST_CASE(FindAllDataMatches)
 {
-  Name nameA  ("ndn:/A");
-  Name nameAB ("ndn:/A/B");
-  Name nameABC("ndn:/A/B/C");
-  Name nameD  ("ndn:/D");
-  Interest interestA (nameA );
-  Interest interestAB(nameAB);
-  Interest interestD (nameD );
+  Name nameA   ("ndn:/A");
+  Name nameAB  ("ndn:/A/B");
+  Name nameABC ("ndn:/A/B/C");
+  Name nameABCD("ndn:/A/B/C/D");
+  Name nameD   ("ndn:/D");
+
+  Interest interestA  (nameA  );
+  Interest interestABC(nameABC);
+  Interest interestD  (nameD  );
 
   NameTree nameTree(16);
   Pit pit(nameTree);
+  int count = 0;
   
   BOOST_CHECK_EQUAL(pit.size(), 0);
 
-  pit.insert(interestA );
-  pit.insert(interestAB);
-  pit.insert(interestD );
+  pit.insert(interestA  );
+  pit.insert(interestABC);
+  pit.insert(interestD  );
+
+  nameTree.lookup(nameABCD); // make sure /A/B/C/D is in nameTree
   
   BOOST_CHECK_EQUAL(pit.size(), 3);
 
-  Data data(nameABC);
+  Data data(nameABCD);
   
   shared_ptr<pit::DataMatchResult> matches = pit.findAllDataMatches(data);
-  int count = 0;
-  bool hasA  = false;
-  bool hasAB = false;
-  bool hasD  = false;
+  
+  bool hasA   = false;
+  bool hasAB  = false;
+  bool hasABC = false;
+  bool hasD   = false;
+
   for (pit::DataMatchResult::iterator it = matches->begin();
        it != matches->end(); ++it) {
     ++count;
     shared_ptr<pit::Entry> entry = *it;
-    if (entry->getName().equals(nameA )) {
-      hasA  = true;
-    }
-    if (entry->getName().equals(nameAB)) {
-      hasAB = true;
-    }
-    if (entry->getName().equals(nameD )) {
-      hasD  = true;
-    }
+
+    if (entry->getName().equals(nameA ))
+      hasA   = true;
+
+    if (entry->getName().equals(nameAB))
+      hasAB  = true;
+  
+    if (entry->getName().equals(nameABC))
+      hasABC = true;
+    
+    if (entry->getName().equals(nameD))
+      hasD   = true;
   }
+  BOOST_CHECK_EQUAL(hasA  , true);
+  BOOST_CHECK_EQUAL(hasAB , false);
+  BOOST_CHECK_EQUAL(hasABC, true);
+  BOOST_CHECK_EQUAL(hasD  , false);
+
   BOOST_CHECK_EQUAL(count, 2);
-  BOOST_CHECK_EQUAL(hasA , true);
-  BOOST_CHECK_EQUAL(hasAB, true);
-  BOOST_CHECK_EQUAL(hasD , false);
+
 }
 
 BOOST_AUTO_TEST_SUITE_END()