blob: 77c978520dd1f87bc180cddd73c214c12082d9f7 [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/*
Junxiao Shicf4ac5b2018-03-28 22:46:06 +00003 * Copyright (c) 2013-2018 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
Davide Pesaventodb4da5e2018-06-15 11:37:52 -040030#include <iterator>
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
Junxiao Shicf4ac5b2018-03-28 22:46:06 +000037 *
38 * NDN Packet Format v0.3 defines name component types other than GenericNameComponent and
39 * ImplicitSha256DigestComponent, and removes Exclude selector. This implementation follows v0.2
40 * semantics and can only store GenericNameComponent and ImplicitSha256DigestComponent.
41 * The behavior of \c isExcluded on a name component of other types is unspecified.
Alexander Afanasyevb3a6af42014-01-03 13:08:28 -080042 */
43class Exclude
44{
45public:
Steve DiBenedetto54ce6682014-07-22 13:22:57 -060046 class Error : public tlv::Error
Alexander Afanasyevff2d08f2014-04-07 18:28:25 -070047 {
48 public:
49 explicit
50 Error(const std::string& what)
Steve DiBenedetto54ce6682014-07-22 13:22:57 -060051 : tlv::Error(what)
Alexander Afanasyevff2d08f2014-04-07 18:28:25 -070052 {
53 }
54 };
Alexander Afanasyev993a0e12014-01-03 13:51:37 -080055
Alexander Afanasyevb3a6af42014-01-03 13:08:28 -080056 /**
Junxiao Shidf4b24e2016-07-14 21:41:43 +000057 * @brief Constructs an empty Exclude
Alexander Afanasyevb3a6af42014-01-03 13:08:28 -080058 */
Alexander Afanasyevff2d08f2014-04-07 18:28:25 -070059 Exclude();
Alexander Afanasyevb3a6af42014-01-03 13:08:28 -080060
61 /**
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -070062 * @brief Create from wire encoding
63 */
64 explicit
Junxiao Shi75203022014-09-11 10:01:50 -070065 Exclude(const Block& wire);
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -070066
67 /**
Alexander Afanasyevc348f832014-02-17 16:35:17 -080068 * @brief Fast encoding or block size estimation
69 */
Alexander Afanasyev74633892015-02-08 18:08:46 -080070 template<encoding::Tag TAG>
Junxiao Shi75203022014-09-11 10:01:50 -070071 size_t
Alexander Afanasyevd5c48e02015-06-24 11:58:14 -070072 wireEncode(EncodingImpl<TAG>& encoder) const;
Alexander Afanasyevff2d08f2014-04-07 18:28:25 -070073
Alexander Afanasyevc348f832014-02-17 16:35:17 -080074 /**
75 * @brief Encode to a wire format
76 */
Junxiao Shi75203022014-09-11 10:01:50 -070077 const Block&
Alexander Afanasyevc348f832014-02-17 16:35:17 -080078 wireEncode() const;
79
80 /**
81 * @brief Decode from the wire format
82 */
Junxiao Shi75203022014-09-11 10:01:50 -070083 void
Alexander Afanasyevff2d08f2014-04-07 18:28:25 -070084 wireDecode(const Block& wire);
85
Junxiao Shi75203022014-09-11 10:01:50 -070086 /**
87 * @brief Get escaped string representation (e.g., for use in URI) of the exclude filter
88 */
89 std::string
90 toUri() const;
Alexander Afanasyevc348f832014-02-17 16:35:17 -080091
Junxiao Shi75203022014-09-11 10:01:50 -070092public: // high-level API
Alexander Afanasyevc348f832014-02-17 16:35:17 -080093 /**
Alexander Afanasyevb3a6af42014-01-03 13:08:28 -080094 * @brief Check if name component is excluded
95 * @param comp Name component to check against exclude filter
96 */
97 bool
Alexander Afanasyevff2d08f2014-04-07 18:28:25 -070098 isExcluded(const name::Component& comp) const;
Alexander Afanasyevb3a6af42014-01-03 13:08:28 -080099
100 /**
101 * @brief Exclude specific name component
102 * @param comp component to exclude
103 * @returns *this to allow chaining
104 */
Alexander Afanasyevff2d08f2014-04-07 18:28:25 -0700105 Exclude&
106 excludeOne(const name::Component& comp);
Alexander Afanasyevb3a6af42014-01-03 13:08:28 -0800107
108 /**
Junxiao Shidf4b24e2016-07-14 21:41:43 +0000109 * @brief Exclude components in range [from, to]
Alexander Afanasyevb3a6af42014-01-03 13:08:28 -0800110 * @param from first element of the range
111 * @param to last element of the range
Junxiao Shidf4b24e2016-07-14 21:41:43 +0000112 * @throw Error \p from equals or comes after \p to in canonical ordering
Alexander Afanasyevb3a6af42014-01-03 13:08:28 -0800113 * @returns *this to allow chaining
114 */
Alexander Afanasyevff2d08f2014-04-07 18:28:25 -0700115 Exclude&
116 excludeRange(const name::Component& from, const name::Component& to);
Alexander Afanasyevb3a6af42014-01-03 13:08:28 -0800117
118 /**
Junxiao Shidf4b24e2016-07-14 21:41:43 +0000119 * @brief Exclude all components in range (-Inf, to]
Alexander Afanasyevb3a6af42014-01-03 13:08:28 -0800120 * @param to last element of the range
121 * @returns *this to allow chaining
122 */
Junxiao Shi75203022014-09-11 10:01:50 -0700123 Exclude&
Alexander Afanasyevff2d08f2014-04-07 18:28:25 -0700124 excludeBefore(const name::Component& to);
Alexander Afanasyevb3a6af42014-01-03 13:08:28 -0800125
126 /**
Junxiao Shidf4b24e2016-07-14 21:41:43 +0000127 * @brief Exclude all components in range [from, +Inf)
Alexander Afanasyev770827c2014-05-13 17:42:55 -0700128 * @param from the first element of the range
Alexander Afanasyevb3a6af42014-01-03 13:08:28 -0800129 * @returns *this to allow chaining
130 */
Alexander Afanasyevff2d08f2014-04-07 18:28:25 -0700131 Exclude&
132 excludeAfter(const name::Component& from);
Alexander Afanasyevb3a6af42014-01-03 13:08:28 -0800133
Alexander Afanasyevba096052014-09-19 15:36:37 -0700134public: // EqualityComparable concept
135 bool
136 operator==(const Exclude& other) const;
137
138 bool
139 operator!=(const Exclude& other) const;
140
Davide Pesavento88a0d812017-08-19 21:31:42 -0400141public: // internal storage
Junxiao Shidf4b24e2016-07-14 21:41:43 +0000142 /**
143 * @brief either a name::Component or "negative infinity"
144 */
145 class ExcludeComponent
146 {
147 public:
148 /**
149 * @brief implicitly construct a regular infinity ExcludeComponent
150 * @param component a name component which is excluded
151 */
152 ExcludeComponent(const name::Component& component);
Junxiao Shi75203022014-09-11 10:01:50 -0700153
Junxiao Shidf4b24e2016-07-14 21:41:43 +0000154 /**
155 * @brief construct a negative infinity ExcludeComponent
156 * @param isNegInf must be true
157 */
158 explicit
159 ExcludeComponent(bool isNegInf);
160
161 public:
162 bool isNegInf;
163 name::Component component;
164 };
Junxiao Shi75203022014-09-11 10:01:50 -0700165
166 /**
Junxiao Shidf4b24e2016-07-14 21:41:43 +0000167 * @brief a map of exclude entries
Alexander Afanasyevb3a6af42014-01-03 13:08:28 -0800168 *
Junxiao Shidf4b24e2016-07-14 21:41:43 +0000169 * Each key, except "negative infinity", is a name component that is excluded.
170 * The mapped boolean indicates whether the range between a key and the next greater key
171 * is also excluded. If true, the wire encoding shall have an ANY element.
Alexander Afanasyevb3a6af42014-01-03 13:08:28 -0800172 *
Junxiao Shidf4b24e2016-07-14 21:41:43 +0000173 * The map is ordered in descending order to simplify \p isExcluded.
Alexander Afanasyevb3a6af42014-01-03 13:08:28 -0800174 */
Junxiao Shib80e9472016-07-20 13:45:24 +0000175 typedef std::map<ExcludeComponent, bool, std::greater<ExcludeComponent>> ExcludeMap;
176 typedef ExcludeMap::value_type Entry;
Alexander Afanasyevb3a6af42014-01-03 13:08:28 -0800177
Junxiao Shib80e9472016-07-20 13:45:24 +0000178public: // enumeration API
Alexander Afanasyevb3a6af42014-01-03 13:08:28 -0800179 /**
Junxiao Shib80e9472016-07-20 13:45:24 +0000180 * @brief represent an excluded component or range
Alexander Afanasyevb3a6af42014-01-03 13:08:28 -0800181 */
Junxiao Shib80e9472016-07-20 13:45:24 +0000182 class Range
183 {
184 public:
Junxiao Shi4f756902017-07-18 03:05:02 +0000185 Range();
186
187 Range(bool fromInfinity, const name::Component& from, bool toInfinity, const name::Component& to);
188
Junxiao Shib80e9472016-07-20 13:45:24 +0000189 /**
190 * @retval true A single component is excluded
191 * @retval false A range of more than one components are excluded
192 */
193 bool
194 isSingular() const;
Alexander Afanasyevb3a6af42014-01-03 13:08:28 -0800195
Junxiao Shib80e9472016-07-20 13:45:24 +0000196 bool
197 operator==(const Exclude::Range& other) const;
198
199 bool
200 operator!=(const Exclude::Range& other) const;
201
202 public:
203 /**
204 * @brief from negative infinity?
205 */
206 bool fromInfinity;
207
208 /**
209 * @brief from component (inclusive)
210 * @pre valid only if !fromInfinity
211 */
212 name::Component from;
213
214 /**
215 * @brief to positive infinity?
216 */
217 bool toInfinity;
218
219 /**
220 * @brief to component (inclusive)
221 * @pre valid only if !toInfinity
222 */
223 name::Component to;
224 };
225
Davide Pesaventodb4da5e2018-06-15 11:37:52 -0400226 class const_iterator
Junxiao Shib80e9472016-07-20 13:45:24 +0000227 {
228 public:
Davide Pesaventodb4da5e2018-06-15 11:37:52 -0400229 using iterator_category = std::forward_iterator_tag;
230 using value_type = const Range;
231 using difference_type = std::ptrdiff_t;
232 using pointer = value_type*;
233 using reference = value_type&;
234
Junxiao Shib80e9472016-07-20 13:45:24 +0000235 const_iterator() = default;
236
237 const_iterator(ExcludeMap::const_reverse_iterator it, ExcludeMap::const_reverse_iterator rend);
238
Davide Pesaventodb4da5e2018-06-15 11:37:52 -0400239 reference
Junxiao Shib80e9472016-07-20 13:45:24 +0000240 operator*() const;
241
Davide Pesaventodb4da5e2018-06-15 11:37:52 -0400242 pointer
Junxiao Shib80e9472016-07-20 13:45:24 +0000243 operator->() const;
244
245 const_iterator&
246 operator++();
247
248 const_iterator
249 operator++(int);
250
251 bool
252 operator==(const const_iterator& other) const;
253
254 bool
255 operator!=(const const_iterator& other) const;
256
257 private:
258 void
259 update();
260
261 private:
262 ExcludeMap::const_reverse_iterator m_it;
263 ExcludeMap::const_reverse_iterator m_rend;
264 Range m_range;
265 friend class Exclude;
266 };
267
Junxiao Shi75203022014-09-11 10:01:50 -0700268 const_iterator
Alexander Afanasyevff2d08f2014-04-07 18:28:25 -0700269 begin() const;
Alexander Afanasyevb3a6af42014-01-03 13:08:28 -0800270
Junxiao Shi75203022014-09-11 10:01:50 -0700271 const_iterator
Alexander Afanasyevff2d08f2014-04-07 18:28:25 -0700272 end() const;
Alexander Afanasyevb3a6af42014-01-03 13:08:28 -0800273
Junxiao Shib80e9472016-07-20 13:45:24 +0000274 bool
275 empty() const;
276
277 size_t
278 size() const;
279
280 /// \todo const_iterator erase(const_iterator i);
281
282 void
283 clear();
284
Alexander Afanasyevb3a6af42014-01-03 13:08:28 -0800285private:
Junxiao Shidf4b24e2016-07-14 21:41:43 +0000286 /**
287 * @brief directly append exclude element
288 * @tparam T either name::Component or bool
289 *
290 * This method is used during conversion from wire format of exclude filter
291 */
292 template<typename T>
293 void
294 appendEntry(const T& component, bool hasAny);
295
Alexander Afanasyevff2d08f2014-04-07 18:28:25 -0700296 Exclude&
Junxiao Shidf4b24e2016-07-14 21:41:43 +0000297 excludeRange(const ExcludeComponent& from, const name::Component& to);
Alexander Afanasyevb3a6af42014-01-03 13:08:28 -0800298
299private:
Junxiao Shib80e9472016-07-20 13:45:24 +0000300 ExcludeMap m_entries;
Alexander Afanasyevff2d08f2014-04-07 18:28:25 -0700301 mutable Block m_wire;
Junxiao Shib80e9472016-07-20 13:45:24 +0000302
303 friend std::ostream&
304 operator<<(std::ostream& os, const Exclude& name);
Alexander Afanasyevb3a6af42014-01-03 13:08:28 -0800305};
306
Davide Pesavento88a0d812017-08-19 21:31:42 -0400307NDN_CXX_DECLARE_WIRE_ENCODE_INSTANTIATIONS(Exclude);
Alexander Afanasyevb3a6af42014-01-03 13:08:28 -0800308
Junxiao Shidf4b24e2016-07-14 21:41:43 +0000309bool
Junxiao Shib80e9472016-07-20 13:45:24 +0000310operator==(const Exclude::ExcludeComponent& a, const Exclude::ExcludeComponent& b);
311
312bool
Junxiao Shidf4b24e2016-07-14 21:41:43 +0000313operator>(const Exclude::ExcludeComponent& a, const Exclude::ExcludeComponent& b);
Alexander Afanasyev993a0e12014-01-03 13:51:37 -0800314
Junxiao Shib80e9472016-07-20 13:45:24 +0000315std::ostream&
316operator<<(std::ostream& os, const Exclude::Range& range);
317
Davide Pesavento88a0d812017-08-19 21:31:42 -0400318std::ostream&
319operator<<(std::ostream& os, const Exclude& name);
320
Junxiao Shib80e9472016-07-20 13:45:24 +0000321inline Exclude::const_iterator
322Exclude::begin() const
323{
324 return const_iterator(m_entries.rbegin(), m_entries.rend());
325}
326
327inline Exclude::const_iterator
328Exclude::end() const
329{
330 return const_iterator(m_entries.rend(), m_entries.rend());
331}
332
Alexander Afanasyevb3a6af42014-01-03 13:08:28 -0800333inline bool
Alexander Afanasyevff2d08f2014-04-07 18:28:25 -0700334Exclude::empty() const
Alexander Afanasyevb3a6af42014-01-03 13:08:28 -0800335{
Junxiao Shidf4b24e2016-07-14 21:41:43 +0000336 return m_entries.empty();
Alexander Afanasyev85480842014-01-06 14:46:54 -0800337}
338
Alexander Afanasyevba096052014-09-19 15:36:37 -0700339inline bool
340Exclude::operator!=(const Exclude& other) const
Alexander Afanasyevb3a6af42014-01-03 13:08:28 -0800341{
Alexander Afanasyevba096052014-09-19 15:36:37 -0700342 return !(*this == other);
Alexander Afanasyevb3a6af42014-01-03 13:08:28 -0800343}
344
Junxiao Shib80e9472016-07-20 13:45:24 +0000345inline bool
346Exclude::Range::isSingular() const
347{
348 return !this->fromInfinity && !this->toInfinity && this->from == this->to;
349}
350
351inline bool
352Exclude::Range::operator!=(const Exclude::Range& other) const
353{
354 return !this->operator==(other);
355}
356
Davide Pesaventodb4da5e2018-06-15 11:37:52 -0400357inline Exclude::const_iterator::reference
Junxiao Shib80e9472016-07-20 13:45:24 +0000358Exclude::const_iterator::operator*() const
359{
360 BOOST_ASSERT(m_it != m_rend);
361 return m_range;
362}
363
Davide Pesaventodb4da5e2018-06-15 11:37:52 -0400364inline Exclude::const_iterator::pointer
Junxiao Shib80e9472016-07-20 13:45:24 +0000365Exclude::const_iterator::operator->() const
366{
367 BOOST_ASSERT(m_it != m_rend);
368 return &m_range;
369}
370
371inline bool
372Exclude::const_iterator::operator==(const const_iterator& other) const
373{
374 return m_it == other.m_it;
375}
376
377inline bool
378Exclude::const_iterator::operator!=(const const_iterator& other) const
379{
380 return !this->operator==(other);
381}
382
Junxiao Shidf4b24e2016-07-14 21:41:43 +0000383} // namespace ndn
Alexander Afanasyevb3a6af42014-01-03 13:08:28 -0800384
Junxiao Shi4f756902017-07-18 03:05:02 +0000385#endif // NDN_EXCLUDE_HPP