blob: b085bb7bb96fadd91b2e8885ea85a5a5b8aad6d9 [file] [log] [blame]
Junxiao Shi029401f2016-08-05 12:55:14 +00001/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
Davide Pesavento981db802018-04-10 18:05:04 -04002/*
Davide Pesavento191a7a22023-05-17 22:40:43 -04003 * Copyright (c) 2014-2023, Regents of the University of California,
Junxiao Shi029401f2016-08-05 12:55:14 +00004 * Arizona Board of Regents,
5 * Colorado State University,
6 * University Pierre & Marie Curie, Sorbonne University,
7 * Washington University in St. Louis,
8 * Beijing Institute of Technology,
9 * The University of Memphis.
10 *
11 * This file is part of NFD (Named Data Networking Forwarding Daemon).
12 * See AUTHORS.md for complete list of NFD authors and contributors.
13 *
14 * NFD is free software: you can redistribute it and/or modify it under the terms
15 * of the GNU General Public License as published by the Free Software Foundation,
16 * either version 3 of the License, or (at your option) any later version.
17 *
18 * NFD is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
19 * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
20 * PURPOSE. See the GNU General Public License for more details.
21 *
22 * You should have received a copy of the GNU General Public License along with
23 * NFD, e.g., in COPYING.md file. If not, see <http://www.gnu.org/licenses/>.
24 */
25
26#include "name-tree-iterator.hpp"
27#include "name-tree.hpp"
Davide Pesavento2cae8ca2019-04-18 20:48:05 -040028#include "common/logger.hpp"
Davide Pesavento981db802018-04-10 18:05:04 -040029
Davide Pesaventoe422f9e2022-06-03 01:30:23 -040030namespace nfd::name_tree {
Junxiao Shi029401f2016-08-05 12:55:14 +000031
Davide Pesaventoa3148082018-04-12 18:21:54 -040032NFD_LOG_INIT(NameTreeIterator);
Junxiao Shi9f6ca602016-08-15 04:50:29 +000033
Davide Pesaventoaa9e3b22022-10-21 17:00:07 -040034Iterator::Iterator() = default;
Junxiao Shi029401f2016-08-05 12:55:14 +000035
Junxiao Shib660b4c2016-08-06 20:47:44 +000036Iterator::Iterator(shared_ptr<EnumerationImpl> impl, const Entry* ref)
Davide Pesaventoe4b22382018-06-10 14:37:24 -040037 : m_impl(std::move(impl))
Junxiao Shi029401f2016-08-05 12:55:14 +000038 , m_ref(ref)
Junxiao Shi029401f2016-08-05 12:55:14 +000039{
40 m_impl->advance(*this);
41 NFD_LOG_TRACE("initialized " << *this);
42}
43
44Iterator&
45Iterator::operator++()
46{
47 BOOST_ASSERT(m_impl != nullptr);
48 m_impl->advance(*this);
49 NFD_LOG_TRACE("advanced " << *this);
50 return *this;
51}
52
Junxiao Shi029401f2016-08-05 12:55:14 +000053std::ostream&
54operator<<(std::ostream& os, const Iterator& i)
55{
56 if (i.m_impl == nullptr) {
57 return os << "end";
58 }
59 if (i.m_entry == nullptr) {
60 return os << "uninitialized";
61 }
62
Junxiao Shie3cf2852016-08-09 03:50:56 +000063 os << "entry=" << i.m_entry->getName();
Junxiao Shi029401f2016-08-05 12:55:14 +000064 if (i.m_ref == nullptr) {
65 os << " ref=null";
66 }
67 else {
Junxiao Shie3cf2852016-08-09 03:50:56 +000068 os << " ref=" << i.m_ref->getName();
Junxiao Shi029401f2016-08-05 12:55:14 +000069 }
70 os << " state=" << i.m_state;
71 return os;
72}
73
Junxiao Shib660b4c2016-08-06 20:47:44 +000074EnumerationImpl::EnumerationImpl(const NameTree& nt)
75 : nt(nt)
76 , ht(nt.m_ht)
Junxiao Shi029401f2016-08-05 12:55:14 +000077{
78}
79
80FullEnumerationImpl::FullEnumerationImpl(const NameTree& nt, const EntrySelector& pred)
81 : EnumerationImpl(nt)
82 , m_pred(pred)
83{
84}
85
86void
87FullEnumerationImpl::advance(Iterator& i)
88{
Junxiao Shib660b4c2016-08-06 20:47:44 +000089 // find first entry
Junxiao Shi029401f2016-08-05 12:55:14 +000090 if (i.m_entry == nullptr) {
Junxiao Shib660b4c2016-08-06 20:47:44 +000091 for (size_t bucket = 0; bucket < ht.getNBuckets(); ++bucket) {
92 const Node* node = ht.getBucket(bucket);
Junxiao Shi029401f2016-08-05 12:55:14 +000093 if (node != nullptr) {
Junxiao Shi340d5532016-08-13 04:00:35 +000094 i.m_entry = &node->entry;
Junxiao Shi029401f2016-08-05 12:55:14 +000095 break;
96 }
97 }
Junxiao Shib660b4c2016-08-06 20:47:44 +000098 if (i.m_entry == nullptr) { // empty enumerable
Junxiao Shi029401f2016-08-05 12:55:14 +000099 i = Iterator();
100 return;
101 }
Junxiao Shib660b4c2016-08-06 20:47:44 +0000102 if (m_pred(*i.m_entry)) { // visit first entry
Junxiao Shi029401f2016-08-05 12:55:14 +0000103 return;
104 }
105 }
106
107 // process entries in same bucket
Junxiao Shib660b4c2016-08-06 20:47:44 +0000108 for (const Node* node = getNode(*i.m_entry)->next; node != nullptr; node = node->next) {
Junxiao Shi340d5532016-08-13 04:00:35 +0000109 if (m_pred(node->entry)) {
110 i.m_entry = &node->entry;
Junxiao Shi029401f2016-08-05 12:55:14 +0000111 return;
112 }
113 }
114
115 // process other buckets
Junxiao Shib660b4c2016-08-06 20:47:44 +0000116 size_t currentBucket = ht.computeBucketIndex(getNode(*i.m_entry)->hash);
117 for (size_t bucket = currentBucket + 1; bucket < ht.getNBuckets(); ++bucket) {
118 for (const Node* node = ht.getBucket(bucket); node != nullptr; node = node->next) {
Junxiao Shi340d5532016-08-13 04:00:35 +0000119 if (m_pred(node->entry)) {
120 i.m_entry = &node->entry;
Junxiao Shi029401f2016-08-05 12:55:14 +0000121 return;
122 }
123 }
124 }
125
126 // reach the end
127 i = Iterator();
128}
129
130PartialEnumerationImpl::PartialEnumerationImpl(const NameTree& nt, const EntrySubTreeSelector& pred)
131 : EnumerationImpl(nt)
132 , m_pred(pred)
133{
134}
135
136void
137PartialEnumerationImpl::advance(Iterator& i)
138{
139 bool wantSelf = false;
140 bool wantChildren = false;
141
142 // initialize: start from root
143 if (i.m_entry == nullptr) {
Junxiao Shib660b4c2016-08-06 20:47:44 +0000144 if (i.m_ref == nullptr) { // root does not exist
Junxiao Shi029401f2016-08-05 12:55:14 +0000145 i = Iterator();
146 return;
147 }
148
149 i.m_entry = i.m_ref;
150 std::tie(wantSelf, wantChildren) = m_pred(*i.m_entry);
151 if (wantSelf) { // visit root
152 i.m_state = wantChildren;
153 return;
154 }
155 }
156 else {
157 wantChildren = static_cast<bool>(i.m_state);
158 }
159 BOOST_ASSERT(i.m_ref != nullptr);
160
161 // pre-order traversal
162 while (i.m_entry != i.m_ref || (wantChildren && i.m_entry->hasChildren())) {
163 if (wantChildren && i.m_entry->hasChildren()) { // process children of m_entry
164 i.m_entry = i.m_entry->getChildren().front();
165 std::tie(wantSelf, wantChildren) = m_pred(*i.m_entry);
166 if (wantSelf) { // visit first child
167 i.m_state = wantChildren;
168 return;
169 }
170 // first child rejected, let while loop process other children (siblings of new m_entry)
171 }
172 else { // process siblings of m_entry
Junxiao Shib660b4c2016-08-06 20:47:44 +0000173 const Entry* parent = i.m_entry->getParent();
174 const std::vector<Entry*>& siblings = parent->getChildren();
Junxiao Shi029401f2016-08-05 12:55:14 +0000175 auto sibling = std::find(siblings.begin(), siblings.end(), i.m_entry);
176 BOOST_ASSERT(sibling != siblings.end());
177 while (++sibling != siblings.end()) {
178 i.m_entry = *sibling;
179 std::tie(wantSelf, wantChildren) = m_pred(*i.m_entry);
180 if (wantSelf) { // visit sibling
181 i.m_state = wantChildren;
182 return;
183 }
184 if (wantChildren) {
185 break; // let outer while loop process children of m_entry
186 }
187 // process next sibling
188 }
189 if (sibling == siblings.end()) { // no more sibling
190 i.m_entry = parent;
191 wantChildren = false;
192 }
193 }
194 }
195
196 // reach the end
197 i = Iterator();
198}
199
200PrefixMatchImpl::PrefixMatchImpl(const NameTree& nt, const EntrySelector& pred)
201 : EnumerationImpl(nt)
202 , m_pred(pred)
203{
204}
205
206void
207PrefixMatchImpl::advance(Iterator& i)
208{
209 if (i.m_entry == nullptr) {
Junxiao Shib660b4c2016-08-06 20:47:44 +0000210 if (i.m_ref == nullptr) { // empty enumerable
Junxiao Shi029401f2016-08-05 12:55:14 +0000211 i = Iterator();
212 return;
213 }
214
215 i.m_entry = i.m_ref;
216 if (m_pred(*i.m_entry)) { // visit starting node
217 return;
218 }
219 }
220
221 // traverse up the tree
222 while ((i.m_entry = i.m_entry->getParent()) != nullptr) {
223 if (m_pred(*i.m_entry)) {
224 return;
225 }
226 }
227
228 // reach the end
229 i = Iterator();
230}
231
Davide Pesaventoe422f9e2022-06-03 01:30:23 -0400232} // namespace nfd::name_tree