table: Allow iteration over CS entries

Change-Id: I23bf0da9a853de70187c9e72a0f7a5cb98107fbd
Refs: #2340
diff --git a/daemon/table/cs.hpp b/daemon/table/cs.hpp
index f683a20..0d989cd 100644
--- a/daemon/table/cs.hpp
+++ b/daemon/table/cs.hpp
@@ -31,7 +31,7 @@
 #define NFD_DAEMON_TABLE_CS_HPP
 
 #include "common.hpp"
-#include "cs-entry.hpp"
+#include "cs-skip-list-entry.hpp"
 
 #include <boost/multi_index/member.hpp>
 #include <boost/multi_index_container.hpp>
@@ -43,14 +43,14 @@
 
 namespace nfd {
 
-typedef std::list<cs::Entry*> SkipListLayer;
+typedef std::list<cs::skip_list::Entry*> SkipListLayer;
 typedef std::list<SkipListLayer*> SkipList;
 
 class StalenessComparator
 {
 public:
   bool
-  operator()(const cs::Entry* entry1, const cs::Entry* entry2) const
+  operator()(const cs::skip_list::Entry* entry1, const cs::skip_list::Entry* entry2) const
   {
     return entry1->getStaleTime() < entry2->getStaleTime();
   }
@@ -60,13 +60,13 @@
 {
 public:
   bool
-  operator()(const cs::Entry* entry1, const cs::Entry* entry2) const
+  operator()(const cs::skip_list::Entry* entry1, const cs::skip_list::Entry* entry2) const
   {
     return entry1->isUnsolicited();
   }
 
   bool
-  operator()(bool isUnsolicited, const cs::Entry* entry) const
+  operator()(bool isUnsolicited, const cs::skip_list::Entry* entry) const
   {
     if (isUnsolicited)
       return true;
@@ -81,7 +81,7 @@
 class byArrival;
 
 typedef boost::multi_index_container<
-  cs::Entry*,
+  cs::skip_list::Entry*,
   boost::multi_index::indexed_by<
 
     // by arrival (FIFO)
@@ -92,14 +92,14 @@
     // index by staleness time
     boost::multi_index::ordered_non_unique<
       boost::multi_index::tag<byStaleness>,
-      boost::multi_index::identity<cs::Entry*>,
+      boost::multi_index::identity<cs::skip_list::Entry*>,
       StalenessComparator
     >,
 
     // unsolicited Data is in the front
     boost::multi_index::ordered_non_unique<
       boost::multi_index::tag<unsolicited>,
-      boost::multi_index::identity<cs::Entry*>,
+      boost::multi_index::identity<cs::skip_list::Entry*>,
       UnsolicitedComparator
     >
 
@@ -155,6 +155,53 @@
   size_t
   size() const;
 
+public: // enumeration
+  class const_iterator;
+
+  /** \brief returns an iterator pointing to the first CS entry
+   *  \note Iteration order is implementation-specific and is undefined
+   *  \note The returned iterator may get invalidated if CS is modified
+   */
+  const_iterator
+  begin() const;
+
+  /** \brief returns an iterator referring to the past-the-end CS entry
+   *  \note The returned iterator may get invalidated if CS is modified
+   */
+  const_iterator
+  end() const;
+
+  class const_iterator : public std::iterator<std::forward_iterator_tag, const cs::Entry>
+  {
+  public:
+    const_iterator() = default;
+
+    const_iterator(SkipListLayer::const_iterator it);
+
+    ~const_iterator();
+
+    reference
+    operator*() const;
+
+    pointer
+    operator->() const;
+
+    const_iterator&
+    operator++();
+
+    const_iterator
+    operator++(int);
+
+    bool
+    operator==(const const_iterator& other) const;
+
+    bool
+    operator!=(const const_iterator& other) const;
+
+  private:
+    SkipListLayer::const_iterator m_skipListIterator;
+  };
+
 protected:
   /** \brief removes one Data packet from Content Store based on replacement policy
    *  \return{ whether the Data was removed }
@@ -181,14 +228,14 @@
    *  \return{ returns a pair containing a pointer to the CS Entry,
    *  and a flag indicating if the entry was newly created (True) or refreshed (False) }
    */
-  std::pair<cs::Entry*, bool>
+  std::pair<cs::skip_list::Entry*, bool>
   insertToSkipList(const Data& data, bool isUnsolicited = false);
 
   /** \brief Removes a specific CS Entry from all layers of a skip list
    *  \return{ returns True if CS Entry was succesfully removed and False if CS Entry was not found}
    */
   bool
-  eraseFromSkipList(cs::Entry* entry);
+  eraseFromSkipList(cs::skip_list::Entry* entry);
 
   /** \brief Prints contents of the skip list, starting from the top layer
    */
@@ -216,7 +263,7 @@
    */
   bool
   doesComplyWithSelectors(const Interest& interest,
-                          cs::Entry* entry,
+                          cs::skip_list::Entry* entry,
                           bool doesInterestContainDigest) const;
 
   /** \brief interprets minSuffixComponent and name lengths to understand if Interest contains
@@ -224,16 +271,78 @@
    *  \return{ True if Interest name contains digest; False otherwise }
    */
   bool
-  recognizeInterestWithDigest(const Interest& interest, cs::Entry* entry) const;
+  recognizeInterestWithDigest(const Interest& interest, cs::skip_list::Entry* entry) const;
 
 private:
   SkipList m_skipList;
   CleanupIndex m_cleanupIndex;
   size_t m_nMaxPackets; // user defined maximum size of the Content Store in packets
   size_t m_nPackets;    // current number of packets in Content Store
-  std::queue<cs::Entry*> m_freeCsEntries; // memory pool
+  std::queue<cs::skip_list::Entry*> m_freeCsEntries; // memory pool
 };
 
+inline Cs::const_iterator
+Cs::begin() const
+{
+  return const_iterator(m_skipList.front()->begin());
+}
+
+inline Cs::const_iterator
+Cs::end() const
+{
+  return const_iterator(m_skipList.front()->end());
+}
+
+inline
+Cs::const_iterator::const_iterator(SkipListLayer::const_iterator it)
+  : m_skipListIterator(it)
+{
+}
+
+inline
+Cs::const_iterator::~const_iterator()
+{
+}
+
+inline Cs::const_iterator&
+Cs::const_iterator::operator++()
+{
+  ++m_skipListIterator;
+  return *this;
+}
+
+inline Cs::const_iterator
+Cs::const_iterator::operator++(int)
+{
+  Cs::const_iterator temp(*this);
+  ++(*this);
+  return temp;
+}
+
+inline Cs::const_iterator::reference
+Cs::const_iterator::operator*() const
+{
+  return *(this->operator->());
+}
+
+inline Cs::const_iterator::pointer
+Cs::const_iterator::operator->() const
+{
+  return *m_skipListIterator;
+}
+
+inline bool
+Cs::const_iterator::operator==(const Cs::const_iterator& other) const
+{
+  return m_skipListIterator == other.m_skipListIterator;
+}
+
+inline bool
+Cs::const_iterator::operator!=(const Cs::const_iterator& other) const
+{
+  return !(*this == other);
+}
+
 } // namespace nfd
 
 #endif // NFD_DAEMON_TABLE_CS_HPP