table: make NameTree::findAllMatches usable with range-based for

refs #2155

Change-Id: I298825145cf544faaeeb9e558f6deb6703d434c0
diff --git a/daemon/table/name-tree.cpp b/daemon/table/name-tree.cpp
index b42b240..31bde14 100644
--- a/daemon/table/name-tree.cpp
+++ b/daemon/table/name-tree.cpp
@@ -1,11 +1,12 @@
 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
 /**
- * Copyright (c) 2014  Regents of the University of California,
- *                     Arizona Board of Regents,
- *                     Colorado State University,
- *                     University Pierre & Marie Curie, Sorbonne University,
- *                     Washington University in St. Louis,
- *                     Beijing Institute of Technology
+ * Copyright (c) 2014,  Regents of the University of California,
+ *                      Arizona Board of Regents,
+ *                      Colorado State University,
+ *                      University Pierre & Marie Curie, Sorbonne University,
+ *                      Washington University in St. Louis,
+ *                      Beijing Institute of Technology,
+ *                      The University of Memphis
  *
  * This file is part of NFD (Named Data Networking Forwarding Daemon).
  * See AUTHORS.md for complete list of NFD authors and contributors.
@@ -20,9 +21,7 @@
  *
  * You should have received a copy of the GNU General Public License along with
  * NFD, e.g., in COPYING.md file.  If not, see <http://www.gnu.org/licenses/>.
- **/
-
-// Name Tree (Name Prefix Hash Table)
+ */
 
 #include "name-tree.hpp"
 #include "core/logger.hpp"
@@ -443,7 +442,7 @@
     }
 }
 
-NameTree::const_iterator
+NameTree::Range
 NameTree::findAllMatches(const Name& prefix,
                          const name_tree::EntrySelector& entrySelector) const
 {
@@ -457,13 +456,12 @@
 
   shared_ptr<name_tree::Entry> entry = findLongestPrefixMatch(prefix, entrySelector);
 
-  if (static_cast<bool>(entry))
-    {
-      const_iterator it(FIND_ALL_MATCHES_TYPE, *this, entry, entrySelector);
-      return it;
-    }
+  if (static_cast<bool>(entry)) {
+    const_iterator begin(FIND_ALL_MATCHES_TYPE, *this, entry, entrySelector);
+    return { begin, end() };
+  }
   // If none of the entry satisfies the requirements, then return the end() iterator.
-  return end();
+  return { end(), end() };
 }
 
 // Hash Table Resize
@@ -762,4 +760,10 @@
   return *this;
 }
 
+NameTree::Range::Range(const_iterator begin, const_iterator end)
+  : m_begin(begin)
+  , m_end(end)
+{
+}
+
 } // namespace nfd
diff --git a/daemon/table/name-tree.hpp b/daemon/table/name-tree.hpp
index 0832a31..2ef032e 100644
--- a/daemon/table/name-tree.hpp
+++ b/daemon/table/name-tree.hpp
@@ -80,6 +80,7 @@
 {
 public:
   class const_iterator;
+  class Range;
 
   explicit
   NameTree(size_t nBuckets = 1024);
@@ -173,10 +174,19 @@
                          const name_tree::EntrySelector& entrySelector =
                          name_tree::AnyEntry()) const;
 
-  /**
-   * \brief Enumerate all the name prefixes that satisfy the prefix and entrySelector
+  /** \brief Enumerate all the name prefixes that satisfy the prefix and entrySelector
+   *  \return an unspecified type that have .begin() and .end() methods
+   *          and is usable with range-based for
+   *
+   *  Example:
+   *  \code{.cpp}
+   *  auto&& allMatches = nt.findAllMatches(Name("/A/B/C"));
+   *  for (const name_tree::Entry& nte : allMatches) {
+   *    ...
+   *  }
+   *  \endcode
    */
-  const_iterator
+  Range
   findAllMatches(const Name& prefix,
                  const name_tree::EntrySelector& entrySelector = name_tree::AnyEntry()) const;
 
@@ -248,6 +258,32 @@
     bool                                        m_shouldVisitChildren;
   };
 
+  /** \brief contains a pair of begin and end iterators
+   *
+   *  This is to be used with range-based for.
+   */
+  class Range
+  {
+  public:
+    Range(const_iterator begin, const_iterator end);
+
+    const_iterator
+    begin() const
+    {
+      return m_begin;
+    }
+
+    const_iterator
+    end() const
+    {
+      return m_end;
+    }
+
+  private:
+    const_iterator m_begin;
+    const_iterator m_end;
+  };
+
 private:
   /**
    * \brief Resize the hash table size when its load factor reaches a threshold.
diff --git a/daemon/table/pit.cpp b/daemon/table/pit.cpp
index 13a11d4..e4199e8 100644
--- a/daemon/table/pit.cpp
+++ b/daemon/table/pit.cpp
@@ -75,13 +75,12 @@
 pit::DataMatchResult
 Pit::findAllDataMatches(const Data& data) const
 {
-  pit::DataMatchResult matches;
-
-  auto allMatchesBegin = m_nameTree.findAllMatches(data.getName(),
+  auto&& ntMatches = m_nameTree.findAllMatches(data.getName(),
     [] (const name_tree::Entry& entry) { return entry.hasPitEntries(); });
-  // TODO: change to range-based for, after #2155
-  for (auto it = allMatchesBegin; it != m_nameTree.end(); ++it) {
-    for (const shared_ptr<pit::Entry>& pitEntry : it->getPitEntries()) {
+
+  pit::DataMatchResult matches;
+  for (const name_tree::Entry& nte : ntMatches) {
+    for (const shared_ptr<pit::Entry>& pitEntry : nte.getPitEntries()) {
       if (pitEntry->getInterest().matchesData(data))
         matches.emplace_back(pitEntry);
     }
diff --git a/tests/daemon/table/name-tree.cpp b/tests/daemon/table/name-tree.cpp
index cd1d894..ebb8550 100644
--- a/tests/daemon/table/name-tree.cpp
+++ b/tests/daemon/table/name-tree.cpp
@@ -737,34 +737,33 @@
 
   counter = 0;
 
-  for (NameTree::const_iterator it = nt.findAllMatches(nameABCDEF);
-      it != nt.end(); it++)
-  {
+  auto&& allMatches = nt.findAllMatches(nameABCDEF);
+  for (const name_tree::Entry& entry : allMatches) {
     counter++;
 
-    if (it->getPrefix() == nameRoot)
+    if (entry.getPrefix() == nameRoot)
       hasRoot   = true;
-    if (it->getPrefix() == nameA)
+    if (entry.getPrefix() == nameA)
       hasA      = true;
-    if (it->getPrefix() == nameAB)
+    if (entry.getPrefix() == nameAB)
       hasAB     = true;
-    if (it->getPrefix() == nameABC)
+    if (entry.getPrefix() == nameABC)
       hasABC    = true;
-    if (it->getPrefix() == nameABCD)
+    if (entry.getPrefix() == nameABCD)
       hasABCD   = true;
-    if (it->getPrefix() == nameABCDE)
+    if (entry.getPrefix() == nameABCDE)
       hasABCDE  = true;
-    if (it->getPrefix() == nameABCDEF)
+    if (entry.getPrefix() == nameABCDEF)
       hasABCDEF = true;
-    if (it->getPrefix() == nameAA)
+    if (entry.getPrefix() == nameAA)
       hasAA     = true;
-    if (it->getPrefix() == nameAAC)
+    if (entry.getPrefix() == nameAAC)
       hasAAC    = true;
-    if (it->getPrefix() == nameAAD)
+    if (entry.getPrefix() == nameAAD)
       hasAAD    = true;
-    if (it->getPrefix() == nameAAD1)
+    if (entry.getPrefix() == nameAAD1)
       hasAAD1   = true;
-    if (it->getPrefix() == nameAAD2)
+    if (entry.getPrefix() == nameAAD2)
       hasAAD2   = true;
   }