blob: a5a2db627bd119a771ab7639d1387cd44afa60ab [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
Alexander Afanasyev258ec2b2014-05-14 16:15:37 -070030#include <map>
31
Alexander Afanasyevb3a6af42014-01-03 13:08:28 -080032namespace ndn {
33
Alexander Afanasyevb3a6af42014-01-03 13:08:28 -080034/**
Junxiao Shidf4b24e2016-07-14 21:41:43 +000035 * @brief Represents Exclude selector in NDN Interest
Junxiao Shicf4ac5b2018-03-28 22:46:06 +000036 *
37 * NDN Packet Format v0.3 defines name component types other than GenericNameComponent and
38 * ImplicitSha256DigestComponent, and removes Exclude selector. This implementation follows v0.2
39 * semantics and can only store GenericNameComponent and ImplicitSha256DigestComponent.
40 * The behavior of \c isExcluded on a name component of other types is unspecified.
Alexander Afanasyevb3a6af42014-01-03 13:08:28 -080041 */
42class Exclude
43{
44public:
Steve DiBenedetto54ce6682014-07-22 13:22:57 -060045 class Error : public tlv::Error
Alexander Afanasyevff2d08f2014-04-07 18:28:25 -070046 {
47 public:
48 explicit
49 Error(const std::string& what)
Steve DiBenedetto54ce6682014-07-22 13:22:57 -060050 : tlv::Error(what)
Alexander Afanasyevff2d08f2014-04-07 18:28:25 -070051 {
52 }
53 };
Alexander Afanasyev993a0e12014-01-03 13:51:37 -080054
Alexander Afanasyevb3a6af42014-01-03 13:08:28 -080055 /**
Junxiao Shidf4b24e2016-07-14 21:41:43 +000056 * @brief Constructs an empty Exclude
Alexander Afanasyevb3a6af42014-01-03 13:08:28 -080057 */
Alexander Afanasyevff2d08f2014-04-07 18:28:25 -070058 Exclude();
Alexander Afanasyevb3a6af42014-01-03 13:08:28 -080059
60 /**
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -070061 * @brief Create from wire encoding
62 */
63 explicit
Junxiao Shi75203022014-09-11 10:01:50 -070064 Exclude(const Block& wire);
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -070065
66 /**
Alexander Afanasyevc348f832014-02-17 16:35:17 -080067 * @brief Fast encoding or block size estimation
68 */
Alexander Afanasyev74633892015-02-08 18:08:46 -080069 template<encoding::Tag TAG>
Junxiao Shi75203022014-09-11 10:01:50 -070070 size_t
Alexander Afanasyevd5c48e02015-06-24 11:58:14 -070071 wireEncode(EncodingImpl<TAG>& encoder) const;
Alexander Afanasyevff2d08f2014-04-07 18:28:25 -070072
Alexander Afanasyevc348f832014-02-17 16:35:17 -080073 /**
74 * @brief Encode to a wire format
75 */
Junxiao Shi75203022014-09-11 10:01:50 -070076 const Block&
Alexander Afanasyevc348f832014-02-17 16:35:17 -080077 wireEncode() const;
78
79 /**
80 * @brief Decode from the wire format
81 */
Junxiao Shi75203022014-09-11 10:01:50 -070082 void
Alexander Afanasyevff2d08f2014-04-07 18:28:25 -070083 wireDecode(const Block& wire);
84
Junxiao Shi75203022014-09-11 10:01:50 -070085 /**
86 * @brief Get escaped string representation (e.g., for use in URI) of the exclude filter
87 */
88 std::string
89 toUri() const;
Alexander Afanasyevc348f832014-02-17 16:35:17 -080090
Junxiao Shi75203022014-09-11 10:01:50 -070091public: // high-level API
Alexander Afanasyevc348f832014-02-17 16:35:17 -080092 /**
Alexander Afanasyevb3a6af42014-01-03 13:08:28 -080093 * @brief Check if name component is excluded
94 * @param comp Name component to check against exclude filter
95 */
96 bool
Alexander Afanasyevff2d08f2014-04-07 18:28:25 -070097 isExcluded(const name::Component& comp) const;
Alexander Afanasyevb3a6af42014-01-03 13:08:28 -080098
99 /**
100 * @brief Exclude specific name component
101 * @param comp component to exclude
102 * @returns *this to allow chaining
103 */
Alexander Afanasyevff2d08f2014-04-07 18:28:25 -0700104 Exclude&
105 excludeOne(const name::Component& comp);
Alexander Afanasyevb3a6af42014-01-03 13:08:28 -0800106
107 /**
Junxiao Shidf4b24e2016-07-14 21:41:43 +0000108 * @brief Exclude components in range [from, to]
Alexander Afanasyevb3a6af42014-01-03 13:08:28 -0800109 * @param from first element of the range
110 * @param to last element of the range
Junxiao Shidf4b24e2016-07-14 21:41:43 +0000111 * @throw Error \p from equals or comes after \p to in canonical ordering
Alexander Afanasyevb3a6af42014-01-03 13:08:28 -0800112 * @returns *this to allow chaining
113 */
Alexander Afanasyevff2d08f2014-04-07 18:28:25 -0700114 Exclude&
115 excludeRange(const name::Component& from, const name::Component& to);
Alexander Afanasyevb3a6af42014-01-03 13:08:28 -0800116
117 /**
Junxiao Shidf4b24e2016-07-14 21:41:43 +0000118 * @brief Exclude all components in range (-Inf, to]
Alexander Afanasyevb3a6af42014-01-03 13:08:28 -0800119 * @param to last element of the range
120 * @returns *this to allow chaining
121 */
Junxiao Shi75203022014-09-11 10:01:50 -0700122 Exclude&
Alexander Afanasyevff2d08f2014-04-07 18:28:25 -0700123 excludeBefore(const name::Component& to);
Alexander Afanasyevb3a6af42014-01-03 13:08:28 -0800124
125 /**
Junxiao Shidf4b24e2016-07-14 21:41:43 +0000126 * @brief Exclude all components in range [from, +Inf)
Alexander Afanasyev770827c2014-05-13 17:42:55 -0700127 * @param from the first element of the range
Alexander Afanasyevb3a6af42014-01-03 13:08:28 -0800128 * @returns *this to allow chaining
129 */
Alexander Afanasyevff2d08f2014-04-07 18:28:25 -0700130 Exclude&
131 excludeAfter(const name::Component& from);
Alexander Afanasyevb3a6af42014-01-03 13:08:28 -0800132
Alexander Afanasyevba096052014-09-19 15:36:37 -0700133public: // EqualityComparable concept
134 bool
135 operator==(const Exclude& other) const;
136
137 bool
138 operator!=(const Exclude& other) const;
139
Davide Pesavento88a0d812017-08-19 21:31:42 -0400140public: // internal storage
Junxiao Shidf4b24e2016-07-14 21:41:43 +0000141 /**
142 * @brief either a name::Component or "negative infinity"
143 */
144 class ExcludeComponent
145 {
146 public:
147 /**
148 * @brief implicitly construct a regular infinity ExcludeComponent
149 * @param component a name component which is excluded
150 */
151 ExcludeComponent(const name::Component& component);
Junxiao Shi75203022014-09-11 10:01:50 -0700152
Junxiao Shidf4b24e2016-07-14 21:41:43 +0000153 /**
154 * @brief construct a negative infinity ExcludeComponent
155 * @param isNegInf must be true
156 */
157 explicit
158 ExcludeComponent(bool isNegInf);
159
160 public:
161 bool isNegInf;
162 name::Component component;
163 };
Junxiao Shi75203022014-09-11 10:01:50 -0700164
165 /**
Junxiao Shidf4b24e2016-07-14 21:41:43 +0000166 * @brief a map of exclude entries
Alexander Afanasyevb3a6af42014-01-03 13:08:28 -0800167 *
Junxiao Shidf4b24e2016-07-14 21:41:43 +0000168 * Each key, except "negative infinity", is a name component that is excluded.
169 * The mapped boolean indicates whether the range between a key and the next greater key
170 * is also excluded. If true, the wire encoding shall have an ANY element.
Alexander Afanasyevb3a6af42014-01-03 13:08:28 -0800171 *
Junxiao Shidf4b24e2016-07-14 21:41:43 +0000172 * The map is ordered in descending order to simplify \p isExcluded.
Alexander Afanasyevb3a6af42014-01-03 13:08:28 -0800173 */
Junxiao Shib80e9472016-07-20 13:45:24 +0000174 typedef std::map<ExcludeComponent, bool, std::greater<ExcludeComponent>> ExcludeMap;
175 typedef ExcludeMap::value_type Entry;
Alexander Afanasyevb3a6af42014-01-03 13:08:28 -0800176
Junxiao Shib80e9472016-07-20 13:45:24 +0000177public: // enumeration API
Alexander Afanasyevb3a6af42014-01-03 13:08:28 -0800178 /**
Junxiao Shib80e9472016-07-20 13:45:24 +0000179 * @brief represent an excluded component or range
Alexander Afanasyevb3a6af42014-01-03 13:08:28 -0800180 */
Junxiao Shib80e9472016-07-20 13:45:24 +0000181 class Range
182 {
183 public:
Junxiao Shi4f756902017-07-18 03:05:02 +0000184 Range();
185
186 Range(bool fromInfinity, const name::Component& from, bool toInfinity, const name::Component& to);
187
Junxiao Shib80e9472016-07-20 13:45:24 +0000188 /**
189 * @retval true A single component is excluded
190 * @retval false A range of more than one components are excluded
191 */
192 bool
193 isSingular() const;
Alexander Afanasyevb3a6af42014-01-03 13:08:28 -0800194
Junxiao Shib80e9472016-07-20 13:45:24 +0000195 bool
196 operator==(const Exclude::Range& other) const;
197
198 bool
199 operator!=(const Exclude::Range& other) const;
200
201 public:
202 /**
203 * @brief from negative infinity?
204 */
205 bool fromInfinity;
206
207 /**
208 * @brief from component (inclusive)
209 * @pre valid only if !fromInfinity
210 */
211 name::Component from;
212
213 /**
214 * @brief to positive infinity?
215 */
216 bool toInfinity;
217
218 /**
219 * @brief to component (inclusive)
220 * @pre valid only if !toInfinity
221 */
222 name::Component to;
223 };
224
225 class const_iterator : public std::iterator<std::forward_iterator_tag, const Range>
226 {
227 public:
228 const_iterator() = default;
229
230 const_iterator(ExcludeMap::const_reverse_iterator it, ExcludeMap::const_reverse_iterator rend);
231
232 const Range&
233 operator*() const;
234
235 const Range*
236 operator->() const;
237
238 const_iterator&
239 operator++();
240
241 const_iterator
242 operator++(int);
243
244 bool
245 operator==(const const_iterator& other) const;
246
247 bool
248 operator!=(const const_iterator& other) const;
249
250 private:
251 void
252 update();
253
254 private:
255 ExcludeMap::const_reverse_iterator m_it;
256 ExcludeMap::const_reverse_iterator m_rend;
257 Range m_range;
258 friend class Exclude;
259 };
260
Junxiao Shi75203022014-09-11 10:01:50 -0700261 const_iterator
Alexander Afanasyevff2d08f2014-04-07 18:28:25 -0700262 begin() const;
Alexander Afanasyevb3a6af42014-01-03 13:08:28 -0800263
Junxiao Shi75203022014-09-11 10:01:50 -0700264 const_iterator
Alexander Afanasyevff2d08f2014-04-07 18:28:25 -0700265 end() const;
Alexander Afanasyevb3a6af42014-01-03 13:08:28 -0800266
Junxiao Shib80e9472016-07-20 13:45:24 +0000267 bool
268 empty() const;
269
270 size_t
271 size() const;
272
273 /// \todo const_iterator erase(const_iterator i);
274
275 void
276 clear();
277
Alexander Afanasyevb3a6af42014-01-03 13:08:28 -0800278private:
Junxiao Shidf4b24e2016-07-14 21:41:43 +0000279 /**
280 * @brief directly append exclude element
281 * @tparam T either name::Component or bool
282 *
283 * This method is used during conversion from wire format of exclude filter
284 */
285 template<typename T>
286 void
287 appendEntry(const T& component, bool hasAny);
288
Alexander Afanasyevff2d08f2014-04-07 18:28:25 -0700289 Exclude&
Junxiao Shidf4b24e2016-07-14 21:41:43 +0000290 excludeRange(const ExcludeComponent& from, const name::Component& to);
Alexander Afanasyevb3a6af42014-01-03 13:08:28 -0800291
292private:
Junxiao Shib80e9472016-07-20 13:45:24 +0000293 ExcludeMap m_entries;
Alexander Afanasyevff2d08f2014-04-07 18:28:25 -0700294 mutable Block m_wire;
Junxiao Shib80e9472016-07-20 13:45:24 +0000295
296 friend std::ostream&
297 operator<<(std::ostream& os, const Exclude& name);
Alexander Afanasyevb3a6af42014-01-03 13:08:28 -0800298};
299
Davide Pesavento88a0d812017-08-19 21:31:42 -0400300NDN_CXX_DECLARE_WIRE_ENCODE_INSTANTIATIONS(Exclude);
Alexander Afanasyevb3a6af42014-01-03 13:08:28 -0800301
Junxiao Shidf4b24e2016-07-14 21:41:43 +0000302bool
Junxiao Shib80e9472016-07-20 13:45:24 +0000303operator==(const Exclude::ExcludeComponent& a, const Exclude::ExcludeComponent& b);
304
305bool
Junxiao Shidf4b24e2016-07-14 21:41:43 +0000306operator>(const Exclude::ExcludeComponent& a, const Exclude::ExcludeComponent& b);
Alexander Afanasyev993a0e12014-01-03 13:51:37 -0800307
Junxiao Shib80e9472016-07-20 13:45:24 +0000308std::ostream&
309operator<<(std::ostream& os, const Exclude::Range& range);
310
Davide Pesavento88a0d812017-08-19 21:31:42 -0400311std::ostream&
312operator<<(std::ostream& os, const Exclude& name);
313
Junxiao Shib80e9472016-07-20 13:45:24 +0000314inline Exclude::const_iterator
315Exclude::begin() const
316{
317 return const_iterator(m_entries.rbegin(), m_entries.rend());
318}
319
320inline Exclude::const_iterator
321Exclude::end() const
322{
323 return const_iterator(m_entries.rend(), m_entries.rend());
324}
325
Alexander Afanasyevb3a6af42014-01-03 13:08:28 -0800326inline bool
Alexander Afanasyevff2d08f2014-04-07 18:28:25 -0700327Exclude::empty() const
Alexander Afanasyevb3a6af42014-01-03 13:08:28 -0800328{
Junxiao Shidf4b24e2016-07-14 21:41:43 +0000329 return m_entries.empty();
Alexander Afanasyev85480842014-01-06 14:46:54 -0800330}
331
Alexander Afanasyevba096052014-09-19 15:36:37 -0700332inline bool
333Exclude::operator!=(const Exclude& other) const
Alexander Afanasyevb3a6af42014-01-03 13:08:28 -0800334{
Alexander Afanasyevba096052014-09-19 15:36:37 -0700335 return !(*this == other);
Alexander Afanasyevb3a6af42014-01-03 13:08:28 -0800336}
337
Junxiao Shib80e9472016-07-20 13:45:24 +0000338inline bool
339Exclude::Range::isSingular() const
340{
341 return !this->fromInfinity && !this->toInfinity && this->from == this->to;
342}
343
344inline bool
345Exclude::Range::operator!=(const Exclude::Range& other) const
346{
347 return !this->operator==(other);
348}
349
350inline const Exclude::Range&
351Exclude::const_iterator::operator*() const
352{
353 BOOST_ASSERT(m_it != m_rend);
354 return m_range;
355}
356
357inline const Exclude::Range*
358Exclude::const_iterator::operator->() const
359{
360 BOOST_ASSERT(m_it != m_rend);
361 return &m_range;
362}
363
364inline bool
365Exclude::const_iterator::operator==(const const_iterator& other) const
366{
367 return m_it == other.m_it;
368}
369
370inline bool
371Exclude::const_iterator::operator!=(const const_iterator& other) const
372{
373 return !this->operator==(other);
374}
375
Junxiao Shidf4b24e2016-07-14 21:41:43 +0000376} // namespace ndn
Alexander Afanasyevb3a6af42014-01-03 13:08:28 -0800377
Junxiao Shi4f756902017-07-18 03:05:02 +0000378#endif // NDN_EXCLUDE_HPP