NS-3 based Named Data Networking (NDN) simulator
ndnSIM 2.3: NDN, CCN, CCNx, content centric networks
API Documentation
name-tree-iterator.cpp
Go to the documentation of this file.
1 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
26 #include "name-tree-iterator.hpp"
27 #include "name-tree.hpp"
28 #include "core/logger.hpp"
29 
30 #include <boost/concept/assert.hpp>
31 #include <boost/concept_check.hpp>
32 #include <boost/range/concepts.hpp>
33 #include <type_traits>
34 
35 namespace nfd {
36 namespace name_tree {
37 
38 BOOST_CONCEPT_ASSERT((boost::ForwardIterator<Iterator>));
39 static_assert(std::is_default_constructible<Iterator>::value,
40  "Iterator must be default-constructible");
41 
42 BOOST_CONCEPT_ASSERT((boost::ForwardRangeConcept<Range>));
43 
44 NFD_LOG_INIT("NameTreeIterator");
45 
47  : m_entry(nullptr)
48  , m_ref(nullptr)
49  , m_state(0)
50 {
51 }
52 
53 Iterator::Iterator(shared_ptr<EnumerationImpl> impl, const Entry* ref)
54  : m_impl(impl)
55  , m_entry(nullptr)
56  , m_ref(ref)
57  , m_state(0)
58 {
59  m_impl->advance(*this);
60  NFD_LOG_TRACE("initialized " << *this);
61 }
62 
63 Iterator&
65 {
66  BOOST_ASSERT(m_impl != nullptr);
67  m_impl->advance(*this);
68  NFD_LOG_TRACE("advanced " << *this);
69  return *this;
70 }
71 
74 {
75  Iterator copy = *this;
76  this->operator++();
77  return copy;
78 }
79 
80 bool
81 Iterator::operator==(const Iterator& other) const
82 {
83  return m_entry == other.m_entry;
84 }
85 
86 std::ostream&
87 operator<<(std::ostream& os, const Iterator& i)
88 {
89  if (i.m_impl == nullptr) {
90  return os << "end";
91  }
92  if (i.m_entry == nullptr) {
93  return os << "uninitialized";
94  }
95 
96  os << "entry=" << i.m_entry->getName();
97  if (i.m_ref == nullptr) {
98  os << " ref=null";
99  }
100  else {
101  os << " ref=" << i.m_ref->getName();
102  }
103  os << " state=" << i.m_state;
104  return os;
105 }
106 
108  : nt(nt)
109  , ht(nt.m_ht)
110 {
111 }
112 
114  : EnumerationImpl(nt)
115  , m_pred(pred)
116 {
117 }
118 
119 void
121 {
122  // find first entry
123  if (i.m_entry == nullptr) {
124  for (size_t bucket = 0; bucket < ht.getNBuckets(); ++bucket) {
125  const Node* node = ht.getBucket(bucket);
126  if (node != nullptr) {
127  i.m_entry = &node->entry;
128  break;
129  }
130  }
131  if (i.m_entry == nullptr) { // empty enumerable
132  i = Iterator();
133  return;
134  }
135  if (m_pred(*i.m_entry)) { // visit first entry
136  return;
137  }
138  }
139 
140  // process entries in same bucket
141  for (const Node* node = getNode(*i.m_entry)->next; node != nullptr; node = node->next) {
142  if (m_pred(node->entry)) {
143  i.m_entry = &node->entry;
144  return;
145  }
146  }
147 
148  // process other buckets
149  size_t currentBucket = ht.computeBucketIndex(getNode(*i.m_entry)->hash);
150  for (size_t bucket = currentBucket + 1; bucket < ht.getNBuckets(); ++bucket) {
151  for (const Node* node = ht.getBucket(bucket); node != nullptr; node = node->next) {
152  if (m_pred(node->entry)) {
153  i.m_entry = &node->entry;
154  return;
155  }
156  }
157  }
158 
159  // reach the end
160  i = Iterator();
161 }
162 
164  : EnumerationImpl(nt)
165  , m_pred(pred)
166 {
167 }
168 
169 void
171 {
172  bool wantSelf = false;
173  bool wantChildren = false;
174 
175  // initialize: start from root
176  if (i.m_entry == nullptr) {
177  if (i.m_ref == nullptr) { // root does not exist
178  i = Iterator();
179  return;
180  }
181 
182  i.m_entry = i.m_ref;
183  std::tie(wantSelf, wantChildren) = m_pred(*i.m_entry);
184  if (wantSelf) { // visit root
185  i.m_state = wantChildren;
186  return;
187  }
188  }
189  else {
190  wantChildren = static_cast<bool>(i.m_state);
191  }
192  BOOST_ASSERT(i.m_ref != nullptr);
193 
194  // pre-order traversal
195  while (i.m_entry != i.m_ref || (wantChildren && i.m_entry->hasChildren())) {
196  if (wantChildren && i.m_entry->hasChildren()) { // process children of m_entry
197  i.m_entry = i.m_entry->getChildren().front();
198  std::tie(wantSelf, wantChildren) = m_pred(*i.m_entry);
199  if (wantSelf) { // visit first child
200  i.m_state = wantChildren;
201  return;
202  }
203  // first child rejected, let while loop process other children (siblings of new m_entry)
204  }
205  else { // process siblings of m_entry
206  const Entry* parent = i.m_entry->getParent();
207  const std::vector<Entry*>& siblings = parent->getChildren();
208  auto sibling = std::find(siblings.begin(), siblings.end(), i.m_entry);
209  BOOST_ASSERT(sibling != siblings.end());
210  while (++sibling != siblings.end()) {
211  i.m_entry = *sibling;
212  std::tie(wantSelf, wantChildren) = m_pred(*i.m_entry);
213  if (wantSelf) { // visit sibling
214  i.m_state = wantChildren;
215  return;
216  }
217  if (wantChildren) {
218  break; // let outer while loop process children of m_entry
219  }
220  // process next sibling
221  }
222  if (sibling == siblings.end()) { // no more sibling
223  i.m_entry = parent;
224  wantChildren = false;
225  }
226  }
227  }
228 
229  // reach the end
230  i = Iterator();
231 }
232 
234  : EnumerationImpl(nt)
235  , m_pred(pred)
236 {
237 }
238 
239 void
240 PrefixMatchImpl::advance(Iterator& i)
241 {
242  if (i.m_entry == nullptr) {
243  if (i.m_ref == nullptr) { // empty enumerable
244  i = Iterator();
245  return;
246  }
247 
248  i.m_entry = i.m_ref;
249  if (m_pred(*i.m_entry)) { // visit starting node
250  return;
251  }
252  }
253 
254  // traverse up the tree
255  while ((i.m_entry = i.m_entry->getParent()) != nullptr) {
256  if (m_pred(*i.m_entry)) {
257  return;
258  }
259  }
260 
261  // reach the end
262  i = Iterator();
263 }
264 
265 } // namespace name_tree
266 } // namespace nfd
bool operator==(const Iterator &other) const
function< std::pair< bool, bool >const Entry &entry)> EntrySubTreeSelector
a predicate to accept or reject an Entry and its children
const Node * getBucket(size_t bucket) const
virtual void advance(Iterator &i) override
size_t computeBucketIndex(HashValue h) const
FullEnumerationImpl(const NameTree &nt, const EntrySelector &pred)
const std::vector< Entry * > & getChildren() const
friend std::ostream & operator<<(std::ostream &, const Iterator &)
#define NFD_LOG_TRACE(expression)
Definition: logger.hpp:54
Copyright (c) 2011-2015 Regents of the University of California.
Definition: ndn-common.hpp:40
function< bool(const Entry &entry)> EntrySelector
a predicate to accept or reject an Entry in find operations
PrefixMatchImpl(const NameTree &nt, const EntrySelector &pred)
Node * getNode(const Entry &entry)
a common index structure for FIB, PIT, StrategyChoice, and Measurements
Definition: name-tree.hpp:36
Entry * getParent() const
#define NFD_LOG_INIT(name)
Definition: logger.hpp:34
virtual void advance(Iterator &i) override
const Name & getName() const
enumeration operation implementation
an entry in the name tree
PartialEnumerationImpl(const NameTree &nt, const EntrySubTreeSelector &pred)