blob: 23dac46658053838abb4569654f2c24ab7500117 [file] [log] [blame]
Alexander Afanasyevc169a812014-05-20 20:37:29 -04001/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
Junxiao Shi4f756902017-07-18 03:05:02 +00002/*
3 * Copyright (c) 2013-2017 Regents of the University of California.
Alexander Afanasyevb3a6af42014-01-03 13:08:28 -08004 *
Alexander Afanasyevdfa52c42014-04-24 21:10:11 -07005 * This file is part of ndn-cxx library (NDN C++ library with eXperimental eXtensions).
Alexander Afanasyevb3a6af42014-01-03 13:08:28 -08006 *
Alexander Afanasyevc169a812014-05-20 20:37:29 -04007 * ndn-cxx library is free software: you can redistribute it and/or modify it under the
8 * terms of the GNU Lesser General Public License as published by the Free Software
9 * Foundation, either version 3 of the License, or (at your option) any later version.
10 *
11 * ndn-cxx library is distributed in the hope that it will be useful, but WITHOUT ANY
12 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
13 * PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
14 *
15 * You should have received copies of the GNU General Public License and GNU Lesser
16 * General Public License along with ndn-cxx, e.g., in COPYING.md file. If not, see
17 * <http://www.gnu.org/licenses/>.
18 *
19 * See AUTHORS.md for complete list of ndn-cxx authors and contributors.
Alexander Afanasyevdfa52c42014-04-24 21:10:11 -070020 *
21 * @author Alexander Afanasyev <http://lasr.cs.ucla.edu/afanasyev/index.html>
Alexander Afanasyevb3a6af42014-01-03 13:08:28 -080022 */
23
Junxiao Shi4f756902017-07-18 03:05:02 +000024#ifndef NDN_EXCLUDE_HPP
25#define NDN_EXCLUDE_HPP
Alexander Afanasyevb3a6af42014-01-03 13:08:28 -080026
Alexander Afanasyevc348f832014-02-17 16:35:17 -080027#include "name-component.hpp"
Alexander Afanasyev15f67312014-07-22 15:11:09 -070028#include "encoding/encoding-buffer.hpp"
Alexander Afanasyevb3a6af42014-01-03 13:08:28 -080029
Alexander Afanasyev15f67312014-07-22 15:11:09 -070030#include <sstream>
Alexander Afanasyev258ec2b2014-05-14 16:15:37 -070031#include <map>
32
Alexander Afanasyevb3a6af42014-01-03 13:08:28 -080033namespace ndn {
34
Alexander Afanasyevb3a6af42014-01-03 13:08:28 -080035/**
Junxiao Shidf4b24e2016-07-14 21:41:43 +000036 * @brief Represents Exclude selector in NDN Interest
Alexander Afanasyevb3a6af42014-01-03 13:08:28 -080037 */
38class Exclude
39{
40public:
Steve DiBenedetto54ce6682014-07-22 13:22:57 -060041 class Error : public tlv::Error
Alexander Afanasyevff2d08f2014-04-07 18:28:25 -070042 {
43 public:
44 explicit
45 Error(const std::string& what)
Steve DiBenedetto54ce6682014-07-22 13:22:57 -060046 : tlv::Error(what)
Alexander Afanasyevff2d08f2014-04-07 18:28:25 -070047 {
48 }
49 };
Alexander Afanasyev993a0e12014-01-03 13:51:37 -080050
Alexander Afanasyevb3a6af42014-01-03 13:08:28 -080051 /**
Junxiao Shidf4b24e2016-07-14 21:41:43 +000052 * @brief Constructs an empty Exclude
Alexander Afanasyevb3a6af42014-01-03 13:08:28 -080053 */
Alexander Afanasyevff2d08f2014-04-07 18:28:25 -070054 Exclude();
Alexander Afanasyevb3a6af42014-01-03 13:08:28 -080055
56 /**
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -070057 * @brief Create from wire encoding
58 */
59 explicit
Junxiao Shi75203022014-09-11 10:01:50 -070060 Exclude(const Block& wire);
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -070061
62 /**
Alexander Afanasyevc348f832014-02-17 16:35:17 -080063 * @brief Fast encoding or block size estimation
64 */
Alexander Afanasyev74633892015-02-08 18:08:46 -080065 template<encoding::Tag TAG>
Junxiao Shi75203022014-09-11 10:01:50 -070066 size_t
Alexander Afanasyevd5c48e02015-06-24 11:58:14 -070067 wireEncode(EncodingImpl<TAG>& encoder) const;
Alexander Afanasyevff2d08f2014-04-07 18:28:25 -070068
Alexander Afanasyevc348f832014-02-17 16:35:17 -080069 /**
70 * @brief Encode to a wire format
71 */
Junxiao Shi75203022014-09-11 10:01:50 -070072 const Block&
Alexander Afanasyevc348f832014-02-17 16:35:17 -080073 wireEncode() const;
74
75 /**
76 * @brief Decode from the wire format
77 */
Junxiao Shi75203022014-09-11 10:01:50 -070078 void
Alexander Afanasyevff2d08f2014-04-07 18:28:25 -070079 wireDecode(const Block& wire);
80
Junxiao Shi75203022014-09-11 10:01:50 -070081 /**
82 * @brief Get escaped string representation (e.g., for use in URI) of the exclude filter
83 */
84 std::string
85 toUri() const;
Alexander Afanasyevc348f832014-02-17 16:35:17 -080086
Junxiao Shi75203022014-09-11 10:01:50 -070087public: // high-level API
Alexander Afanasyevc348f832014-02-17 16:35:17 -080088 /**
Alexander Afanasyevb3a6af42014-01-03 13:08:28 -080089 * @brief Check if name component is excluded
90 * @param comp Name component to check against exclude filter
91 */
92 bool
Alexander Afanasyevff2d08f2014-04-07 18:28:25 -070093 isExcluded(const name::Component& comp) const;
Alexander Afanasyevb3a6af42014-01-03 13:08:28 -080094
95 /**
96 * @brief Exclude specific name component
97 * @param comp component to exclude
98 * @returns *this to allow chaining
99 */
Alexander Afanasyevff2d08f2014-04-07 18:28:25 -0700100 Exclude&
101 excludeOne(const name::Component& comp);
Alexander Afanasyevb3a6af42014-01-03 13:08:28 -0800102
103 /**
Junxiao Shidf4b24e2016-07-14 21:41:43 +0000104 * @brief Exclude components in range [from, to]
Alexander Afanasyevb3a6af42014-01-03 13:08:28 -0800105 * @param from first element of the range
106 * @param to last element of the range
Junxiao Shidf4b24e2016-07-14 21:41:43 +0000107 * @throw Error \p from equals or comes after \p to in canonical ordering
Alexander Afanasyevb3a6af42014-01-03 13:08:28 -0800108 * @returns *this to allow chaining
109 */
Alexander Afanasyevff2d08f2014-04-07 18:28:25 -0700110 Exclude&
111 excludeRange(const name::Component& from, const name::Component& to);
Alexander Afanasyevb3a6af42014-01-03 13:08:28 -0800112
113 /**
Junxiao Shidf4b24e2016-07-14 21:41:43 +0000114 * @brief Exclude all components in range (-Inf, to]
Alexander Afanasyevb3a6af42014-01-03 13:08:28 -0800115 * @param to last element of the range
116 * @returns *this to allow chaining
117 */
Junxiao Shi75203022014-09-11 10:01:50 -0700118 Exclude&
Alexander Afanasyevff2d08f2014-04-07 18:28:25 -0700119 excludeBefore(const name::Component& to);
Alexander Afanasyevb3a6af42014-01-03 13:08:28 -0800120
121 /**
Junxiao Shidf4b24e2016-07-14 21:41:43 +0000122 * @brief Exclude all components in range [from, +Inf)
Alexander Afanasyev770827c2014-05-13 17:42:55 -0700123 * @param from the first element of the range
Alexander Afanasyevb3a6af42014-01-03 13:08:28 -0800124 * @returns *this to allow chaining
125 */
Alexander Afanasyevff2d08f2014-04-07 18:28:25 -0700126 Exclude&
127 excludeAfter(const name::Component& from);
Alexander Afanasyevb3a6af42014-01-03 13:08:28 -0800128
Alexander Afanasyevba096052014-09-19 15:36:37 -0700129public: // EqualityComparable concept
130 bool
131 operator==(const Exclude& other) const;
132
133 bool
134 operator!=(const Exclude& other) const;
135
Junxiao Shib80e9472016-07-20 13:45:24 +0000136public: // interal storage
Junxiao Shidf4b24e2016-07-14 21:41:43 +0000137 /**
138 * @brief either a name::Component or "negative infinity"
139 */
140 class ExcludeComponent
141 {
142 public:
143 /**
144 * @brief implicitly construct a regular infinity ExcludeComponent
145 * @param component a name component which is excluded
146 */
147 ExcludeComponent(const name::Component& component);
Junxiao Shi75203022014-09-11 10:01:50 -0700148
Junxiao Shidf4b24e2016-07-14 21:41:43 +0000149 /**
150 * @brief construct a negative infinity ExcludeComponent
151 * @param isNegInf must be true
152 */
153 explicit
154 ExcludeComponent(bool isNegInf);
155
156 public:
157 bool isNegInf;
158 name::Component component;
159 };
Junxiao Shi75203022014-09-11 10:01:50 -0700160
161 /**
Junxiao Shidf4b24e2016-07-14 21:41:43 +0000162 * @brief a map of exclude entries
Alexander Afanasyevb3a6af42014-01-03 13:08:28 -0800163 *
Junxiao Shidf4b24e2016-07-14 21:41:43 +0000164 * Each key, except "negative infinity", is a name component that is excluded.
165 * The mapped boolean indicates whether the range between a key and the next greater key
166 * is also excluded. If true, the wire encoding shall have an ANY element.
Alexander Afanasyevb3a6af42014-01-03 13:08:28 -0800167 *
Junxiao Shidf4b24e2016-07-14 21:41:43 +0000168 * The map is ordered in descending order to simplify \p isExcluded.
Alexander Afanasyevb3a6af42014-01-03 13:08:28 -0800169 */
Junxiao Shib80e9472016-07-20 13:45:24 +0000170 typedef std::map<ExcludeComponent, bool, std::greater<ExcludeComponent>> ExcludeMap;
171 typedef ExcludeMap::value_type Entry;
Alexander Afanasyevb3a6af42014-01-03 13:08:28 -0800172
Junxiao Shib80e9472016-07-20 13:45:24 +0000173public: // enumeration API
Alexander Afanasyevb3a6af42014-01-03 13:08:28 -0800174 /**
Junxiao Shib80e9472016-07-20 13:45:24 +0000175 * @brief represent an excluded component or range
Alexander Afanasyevb3a6af42014-01-03 13:08:28 -0800176 */
Junxiao Shib80e9472016-07-20 13:45:24 +0000177 class Range
178 {
179 public:
Junxiao Shi4f756902017-07-18 03:05:02 +0000180 Range();
181
182 Range(bool fromInfinity, const name::Component& from, bool toInfinity, const name::Component& to);
183
Junxiao Shib80e9472016-07-20 13:45:24 +0000184 /**
185 * @retval true A single component is excluded
186 * @retval false A range of more than one components are excluded
187 */
188 bool
189 isSingular() const;
Alexander Afanasyevb3a6af42014-01-03 13:08:28 -0800190
Junxiao Shib80e9472016-07-20 13:45:24 +0000191 bool
192 operator==(const Exclude::Range& other) const;
193
194 bool
195 operator!=(const Exclude::Range& other) const;
196
197 public:
198 /**
199 * @brief from negative infinity?
200 */
201 bool fromInfinity;
202
203 /**
204 * @brief from component (inclusive)
205 * @pre valid only if !fromInfinity
206 */
207 name::Component from;
208
209 /**
210 * @brief to positive infinity?
211 */
212 bool toInfinity;
213
214 /**
215 * @brief to component (inclusive)
216 * @pre valid only if !toInfinity
217 */
218 name::Component to;
219 };
220
221 class const_iterator : public std::iterator<std::forward_iterator_tag, const Range>
222 {
223 public:
224 const_iterator() = default;
225
226 const_iterator(ExcludeMap::const_reverse_iterator it, ExcludeMap::const_reverse_iterator rend);
227
228 const Range&
229 operator*() const;
230
231 const Range*
232 operator->() const;
233
234 const_iterator&
235 operator++();
236
237 const_iterator
238 operator++(int);
239
240 bool
241 operator==(const const_iterator& other) const;
242
243 bool
244 operator!=(const const_iterator& other) const;
245
246 private:
247 void
248 update();
249
250 private:
251 ExcludeMap::const_reverse_iterator m_it;
252 ExcludeMap::const_reverse_iterator m_rend;
253 Range m_range;
254 friend class Exclude;
255 };
256
Junxiao Shi75203022014-09-11 10:01:50 -0700257 const_iterator
Alexander Afanasyevff2d08f2014-04-07 18:28:25 -0700258 begin() const;
Alexander Afanasyevb3a6af42014-01-03 13:08:28 -0800259
Junxiao Shi75203022014-09-11 10:01:50 -0700260 const_iterator
Alexander Afanasyevff2d08f2014-04-07 18:28:25 -0700261 end() const;
Alexander Afanasyevb3a6af42014-01-03 13:08:28 -0800262
Junxiao Shib80e9472016-07-20 13:45:24 +0000263 bool
264 empty() const;
265
266 size_t
267 size() const;
268
269 /// \todo const_iterator erase(const_iterator i);
270
271 void
272 clear();
273
Alexander Afanasyevb3a6af42014-01-03 13:08:28 -0800274private:
Junxiao Shidf4b24e2016-07-14 21:41:43 +0000275 /**
276 * @brief directly append exclude element
277 * @tparam T either name::Component or bool
278 *
279 * This method is used during conversion from wire format of exclude filter
280 */
281 template<typename T>
282 void
283 appendEntry(const T& component, bool hasAny);
284
Alexander Afanasyevff2d08f2014-04-07 18:28:25 -0700285 Exclude&
Junxiao Shidf4b24e2016-07-14 21:41:43 +0000286 excludeRange(const ExcludeComponent& from, const name::Component& to);
Alexander Afanasyevb3a6af42014-01-03 13:08:28 -0800287
288private:
Junxiao Shib80e9472016-07-20 13:45:24 +0000289 ExcludeMap m_entries;
Alexander Afanasyevff2d08f2014-04-07 18:28:25 -0700290 mutable Block m_wire;
Junxiao Shib80e9472016-07-20 13:45:24 +0000291
292 friend std::ostream&
293 operator<<(std::ostream& os, const Exclude& name);
Alexander Afanasyevb3a6af42014-01-03 13:08:28 -0800294};
295
296std::ostream&
Alexander Afanasyevff2d08f2014-04-07 18:28:25 -0700297operator<<(std::ostream& os, const Exclude& name);
Alexander Afanasyevb3a6af42014-01-03 13:08:28 -0800298
Junxiao Shidf4b24e2016-07-14 21:41:43 +0000299bool
Junxiao Shib80e9472016-07-20 13:45:24 +0000300operator==(const Exclude::ExcludeComponent& a, const Exclude::ExcludeComponent& b);
301
302bool
Junxiao Shidf4b24e2016-07-14 21:41:43 +0000303operator>(const Exclude::ExcludeComponent& a, const Exclude::ExcludeComponent& b);
Alexander Afanasyev993a0e12014-01-03 13:51:37 -0800304
Junxiao Shib80e9472016-07-20 13:45:24 +0000305std::ostream&
306operator<<(std::ostream& os, const Exclude::Range& range);
307
308inline Exclude::const_iterator
309Exclude::begin() const
310{
311 return const_iterator(m_entries.rbegin(), m_entries.rend());
312}
313
314inline Exclude::const_iterator
315Exclude::end() const
316{
317 return const_iterator(m_entries.rend(), m_entries.rend());
318}
319
Alexander Afanasyevb3a6af42014-01-03 13:08:28 -0800320inline bool
Alexander Afanasyevff2d08f2014-04-07 18:28:25 -0700321Exclude::empty() const
Alexander Afanasyevb3a6af42014-01-03 13:08:28 -0800322{
Junxiao Shidf4b24e2016-07-14 21:41:43 +0000323 return m_entries.empty();
Alexander Afanasyev85480842014-01-06 14:46:54 -0800324}
325
Alexander Afanasyevba096052014-09-19 15:36:37 -0700326inline bool
327Exclude::operator!=(const Exclude& other) const
Alexander Afanasyevb3a6af42014-01-03 13:08:28 -0800328{
Alexander Afanasyevba096052014-09-19 15:36:37 -0700329 return !(*this == other);
Alexander Afanasyevb3a6af42014-01-03 13:08:28 -0800330}
331
Junxiao Shib80e9472016-07-20 13:45:24 +0000332inline bool
333Exclude::Range::isSingular() const
334{
335 return !this->fromInfinity && !this->toInfinity && this->from == this->to;
336}
337
338inline bool
339Exclude::Range::operator!=(const Exclude::Range& other) const
340{
341 return !this->operator==(other);
342}
343
344inline const Exclude::Range&
345Exclude::const_iterator::operator*() const
346{
347 BOOST_ASSERT(m_it != m_rend);
348 return m_range;
349}
350
351inline const Exclude::Range*
352Exclude::const_iterator::operator->() const
353{
354 BOOST_ASSERT(m_it != m_rend);
355 return &m_range;
356}
357
358inline bool
359Exclude::const_iterator::operator==(const const_iterator& other) const
360{
361 return m_it == other.m_it;
362}
363
364inline bool
365Exclude::const_iterator::operator!=(const const_iterator& other) const
366{
367 return !this->operator==(other);
368}
369
Junxiao Shidf4b24e2016-07-14 21:41:43 +0000370} // namespace ndn
Alexander Afanasyevb3a6af42014-01-03 13:08:28 -0800371
Junxiao Shi4f756902017-07-18 03:05:02 +0000372#endif // NDN_EXCLUDE_HPP