table: simplify FIB iterator with Boost.Range

refs #3738

Change-Id: I0bfe985c9dac86a67988f77a89f4d2694c4fd9f5
diff --git a/daemon/table/fib.cpp b/daemon/table/fib.cpp
index 022bb93..8ba6ffe 100644
--- a/daemon/table/fib.cpp
+++ b/daemon/table/fib.cpp
@@ -155,10 +155,11 @@
   }
 }
 
-Fib::const_iterator
-Fib::begin() const
+Fib::Range
+Fib::getRange() const
 {
-  return const_iterator(m_nameTree.fullEnumerate(&nteHasFibEntry).begin());
+  return m_nameTree.fullEnumerate(&nteHasFibEntry) |
+         boost::adaptors::transformed(name_tree::GetTableEntry<Entry>(&name_tree::Entry::getFibEntry));
 }
 
 } // namespace fib
diff --git a/daemon/table/fib.hpp b/daemon/table/fib.hpp
index eb10850..73e0e21 100644
--- a/daemon/table/fib.hpp
+++ b/daemon/table/fib.hpp
@@ -29,6 +29,8 @@
 #include "fib-entry.hpp"
 #include "name-tree.hpp"
 
+#include <boost/range/adaptor/transformed.hpp>
+
 namespace nfd {
 
 namespace measurements {
@@ -49,7 +51,10 @@
   Fib(NameTree& nameTree);
 
   size_t
-  size() const;
+  size() const
+  {
+    return m_nItems;
+  }
 
 public: // lookup
   /** \brief performs a longest prefix match
@@ -97,7 +102,8 @@
   removeNextHop(Entry& entry, const Face& face);
 
 public: // enumeration
-  class const_iterator;
+  typedef boost::transformed_range<name_tree::GetTableEntry<Entry>, const name_tree::Range> Range;
+  typedef boost::range_iterator<Range>::type const_iterator;
 
   /** \brief returns an iterator pointing to the first FIB entry
    *  \note Iteration order is implementation-specific and is undefined
@@ -105,46 +111,20 @@
    *        table is modified
    */
   const_iterator
-  begin() const;
+  begin() const
+  {
+    return this->getRange().begin();
+  }
 
   /** \brief returns an iterator referring to the past-the-end FIB entry
    *  \note The returned iterator may get invalidated if FIB or another NameTree-based
    *        table is modified
    */
   const_iterator
-  end() const;
-
-  class const_iterator : public std::iterator<std::forward_iterator_tag, const Entry>
+  end() const
   {
-  public:
-    const_iterator() = default;
-
-    explicit
-    const_iterator(const NameTree::const_iterator& it);
-
-    ~const_iterator();
-
-    const Entry&
-    operator*() const;
-
-    const 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:
-    NameTree::const_iterator m_nameTreeIterator;
-  };
+    return this->getRange().end();
+  }
 
 private:
   /** \tparam K a parameter acceptable to NameTree::findLongestPrefixMatch
@@ -156,6 +136,9 @@
   void
   erase(name_tree::Entry* nte, bool canDeleteNte = true);
 
+  Range
+  getRange() const;
+
 private:
   NameTree& m_nameTree;
   size_t m_nItems;
@@ -168,69 +151,6 @@
   static const unique_ptr<Entry> s_emptyEntry;
 };
 
-inline size_t
-Fib::size() const
-{
-  return m_nItems;
-}
-
-inline Fib::const_iterator
-Fib::end() const
-{
-  return const_iterator(m_nameTree.end());
-}
-
-inline
-Fib::const_iterator::const_iterator(const NameTree::const_iterator& it)
-  : m_nameTreeIterator(it)
-{
-}
-
-inline
-Fib::const_iterator::~const_iterator()
-{
-}
-
-inline
-Fib::const_iterator
-Fib::const_iterator::operator++(int)
-{
-  const_iterator temp(*this);
-  ++(*this);
-  return temp;
-}
-
-inline Fib::const_iterator&
-Fib::const_iterator::operator++()
-{
-  ++m_nameTreeIterator;
-  return *this;
-}
-
-inline const Entry&
-Fib::const_iterator::operator*() const
-{
-  return *m_nameTreeIterator->getFibEntry();
-}
-
-inline const Entry*
-Fib::const_iterator::operator->() const
-{
-  return m_nameTreeIterator->getFibEntry();
-}
-
-inline bool
-Fib::const_iterator::operator==(const const_iterator& other) const
-{
-  return m_nameTreeIterator == other.m_nameTreeIterator;
-}
-
-inline bool
-Fib::const_iterator::operator!=(const const_iterator& other) const
-{
-  return m_nameTreeIterator != other.m_nameTreeIterator;
-}
-
 } // namespace fib
 
 using fib::Fib;
diff --git a/daemon/table/name-tree-entry.hpp b/daemon/table/name-tree-entry.hpp
index b36aae9..ab385da 100644
--- a/daemon/table/name-tree-entry.hpp
+++ b/daemon/table/name-tree-entry.hpp
@@ -178,6 +178,33 @@
   friend Node* getNode(const Entry& entry);
 };
 
+/** \brief a functor to get a table entry from a name tree entry
+ *  \tparam ENTRY type of single table entry attached to name tree entry, such as fib::Entry
+ */
+template<typename ENTRY>
+class GetTableEntry
+{
+public:
+  /** \brief a function pointer to the getter on Entry class that returns ENTRY
+   */
+  using Getter = ENTRY* (Entry::*)() const;
+
+  explicit
+  GetTableEntry(Getter getter)
+    : m_getter(getter)
+  {
+  }
+
+  const ENTRY&
+  operator()(const Entry& nte) const
+  {
+    return *(nte.*m_getter)();
+  }
+
+private:
+  Getter m_getter;
+};
+
 } // namespace name_tree
 } // namespace nfd