blob: 6e720c85ed8bc925410b32681c85df8ce5198d25 [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:
Junxiao Shi68b53852018-07-25 13:56:38 -060049 using tlv::Error::Error;
Alexander Afanasyevff2d08f2014-04-07 18:28:25 -070050 };
Alexander Afanasyev993a0e12014-01-03 13:51:37 -080051
Alexander Afanasyevb3a6af42014-01-03 13:08:28 -080052 /**
Junxiao Shidf4b24e2016-07-14 21:41:43 +000053 * @brief Constructs an empty Exclude
Alexander Afanasyevb3a6af42014-01-03 13:08:28 -080054 */
Alexander Afanasyevff2d08f2014-04-07 18:28:25 -070055 Exclude();
Alexander Afanasyevb3a6af42014-01-03 13:08:28 -080056
57 /**
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -070058 * @brief Create from wire encoding
59 */
60 explicit
Junxiao Shi75203022014-09-11 10:01:50 -070061 Exclude(const Block& wire);
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -070062
63 /**
Alexander Afanasyevc348f832014-02-17 16:35:17 -080064 * @brief Fast encoding or block size estimation
65 */
Alexander Afanasyev74633892015-02-08 18:08:46 -080066 template<encoding::Tag TAG>
Junxiao Shi75203022014-09-11 10:01:50 -070067 size_t
Alexander Afanasyevd5c48e02015-06-24 11:58:14 -070068 wireEncode(EncodingImpl<TAG>& encoder) const;
Alexander Afanasyevff2d08f2014-04-07 18:28:25 -070069
Alexander Afanasyevc348f832014-02-17 16:35:17 -080070 /**
71 * @brief Encode to a wire format
72 */
Junxiao Shi75203022014-09-11 10:01:50 -070073 const Block&
Alexander Afanasyevc348f832014-02-17 16:35:17 -080074 wireEncode() const;
75
76 /**
77 * @brief Decode from the wire format
78 */
Junxiao Shi75203022014-09-11 10:01:50 -070079 void
Alexander Afanasyevff2d08f2014-04-07 18:28:25 -070080 wireDecode(const Block& wire);
81
Junxiao Shi75203022014-09-11 10:01:50 -070082 /**
83 * @brief Get escaped string representation (e.g., for use in URI) of the exclude filter
84 */
85 std::string
86 toUri() const;
Alexander Afanasyevc348f832014-02-17 16:35:17 -080087
Junxiao Shi75203022014-09-11 10:01:50 -070088public: // high-level API
Alexander Afanasyevc348f832014-02-17 16:35:17 -080089 /**
Alexander Afanasyevb3a6af42014-01-03 13:08:28 -080090 * @brief Check if name component is excluded
91 * @param comp Name component to check against exclude filter
92 */
93 bool
Alexander Afanasyevff2d08f2014-04-07 18:28:25 -070094 isExcluded(const name::Component& comp) const;
Alexander Afanasyevb3a6af42014-01-03 13:08:28 -080095
96 /**
97 * @brief Exclude specific name component
98 * @param comp component to exclude
99 * @returns *this to allow chaining
100 */
Alexander Afanasyevff2d08f2014-04-07 18:28:25 -0700101 Exclude&
102 excludeOne(const name::Component& comp);
Alexander Afanasyevb3a6af42014-01-03 13:08:28 -0800103
104 /**
Junxiao Shidf4b24e2016-07-14 21:41:43 +0000105 * @brief Exclude components in range [from, to]
Alexander Afanasyevb3a6af42014-01-03 13:08:28 -0800106 * @param from first element of the range
107 * @param to last element of the range
Junxiao Shidf4b24e2016-07-14 21:41:43 +0000108 * @throw Error \p from equals or comes after \p to in canonical ordering
Alexander Afanasyevb3a6af42014-01-03 13:08:28 -0800109 * @returns *this to allow chaining
110 */
Alexander Afanasyevff2d08f2014-04-07 18:28:25 -0700111 Exclude&
112 excludeRange(const name::Component& from, const name::Component& to);
Alexander Afanasyevb3a6af42014-01-03 13:08:28 -0800113
114 /**
Junxiao Shidf4b24e2016-07-14 21:41:43 +0000115 * @brief Exclude all components in range (-Inf, to]
Alexander Afanasyevb3a6af42014-01-03 13:08:28 -0800116 * @param to last element of the range
117 * @returns *this to allow chaining
118 */
Junxiao Shi75203022014-09-11 10:01:50 -0700119 Exclude&
Alexander Afanasyevff2d08f2014-04-07 18:28:25 -0700120 excludeBefore(const name::Component& to);
Alexander Afanasyevb3a6af42014-01-03 13:08:28 -0800121
122 /**
Junxiao Shidf4b24e2016-07-14 21:41:43 +0000123 * @brief Exclude all components in range [from, +Inf)
Alexander Afanasyev770827c2014-05-13 17:42:55 -0700124 * @param from the first element of the range
Alexander Afanasyevb3a6af42014-01-03 13:08:28 -0800125 * @returns *this to allow chaining
126 */
Alexander Afanasyevff2d08f2014-04-07 18:28:25 -0700127 Exclude&
128 excludeAfter(const name::Component& from);
Alexander Afanasyevb3a6af42014-01-03 13:08:28 -0800129
Alexander Afanasyevba096052014-09-19 15:36:37 -0700130public: // EqualityComparable concept
131 bool
132 operator==(const Exclude& other) const;
133
134 bool
135 operator!=(const Exclude& other) const;
136
Davide Pesavento88a0d812017-08-19 21:31:42 -0400137public: // internal storage
Junxiao Shidf4b24e2016-07-14 21:41:43 +0000138 /**
139 * @brief either a name::Component or "negative infinity"
140 */
141 class ExcludeComponent
142 {
143 public:
144 /**
145 * @brief implicitly construct a regular infinity ExcludeComponent
146 * @param component a name component which is excluded
147 */
148 ExcludeComponent(const name::Component& component);
Junxiao Shi75203022014-09-11 10:01:50 -0700149
Junxiao Shidf4b24e2016-07-14 21:41:43 +0000150 /**
151 * @brief construct a negative infinity ExcludeComponent
152 * @param isNegInf must be true
153 */
154 explicit
155 ExcludeComponent(bool isNegInf);
156
157 public:
158 bool isNegInf;
159 name::Component component;
160 };
Junxiao Shi75203022014-09-11 10:01:50 -0700161
162 /**
Junxiao Shidf4b24e2016-07-14 21:41:43 +0000163 * @brief a map of exclude entries
Alexander Afanasyevb3a6af42014-01-03 13:08:28 -0800164 *
Junxiao Shidf4b24e2016-07-14 21:41:43 +0000165 * Each key, except "negative infinity", is a name component that is excluded.
166 * The mapped boolean indicates whether the range between a key and the next greater key
167 * is also excluded. If true, the wire encoding shall have an ANY element.
Alexander Afanasyevb3a6af42014-01-03 13:08:28 -0800168 *
Junxiao Shidf4b24e2016-07-14 21:41:43 +0000169 * The map is ordered in descending order to simplify \p isExcluded.
Alexander Afanasyevb3a6af42014-01-03 13:08:28 -0800170 */
Junxiao Shib80e9472016-07-20 13:45:24 +0000171 typedef std::map<ExcludeComponent, bool, std::greater<ExcludeComponent>> ExcludeMap;
172 typedef ExcludeMap::value_type Entry;
Alexander Afanasyevb3a6af42014-01-03 13:08:28 -0800173
Junxiao Shib80e9472016-07-20 13:45:24 +0000174public: // enumeration API
Alexander Afanasyevb3a6af42014-01-03 13:08:28 -0800175 /**
Junxiao Shib80e9472016-07-20 13:45:24 +0000176 * @brief represent an excluded component or range
Alexander Afanasyevb3a6af42014-01-03 13:08:28 -0800177 */
Junxiao Shib80e9472016-07-20 13:45:24 +0000178 class Range
179 {
180 public:
Junxiao Shi4f756902017-07-18 03:05:02 +0000181 Range();
182
183 Range(bool fromInfinity, const name::Component& from, bool toInfinity, const name::Component& to);
184
Junxiao Shib80e9472016-07-20 13:45:24 +0000185 /**
186 * @retval true A single component is excluded
187 * @retval false A range of more than one components are excluded
188 */
189 bool
190 isSingular() const;
Alexander Afanasyevb3a6af42014-01-03 13:08:28 -0800191
Junxiao Shib80e9472016-07-20 13:45:24 +0000192 bool
193 operator==(const Exclude::Range& other) const;
194
195 bool
196 operator!=(const Exclude::Range& other) const;
197
198 public:
199 /**
200 * @brief from negative infinity?
201 */
202 bool fromInfinity;
203
204 /**
205 * @brief from component (inclusive)
206 * @pre valid only if !fromInfinity
207 */
208 name::Component from;
209
210 /**
211 * @brief to positive infinity?
212 */
213 bool toInfinity;
214
215 /**
216 * @brief to component (inclusive)
217 * @pre valid only if !toInfinity
218 */
219 name::Component to;
220 };
221
Davide Pesaventodb4da5e2018-06-15 11:37:52 -0400222 class const_iterator
Junxiao Shib80e9472016-07-20 13:45:24 +0000223 {
224 public:
Davide Pesaventodb4da5e2018-06-15 11:37:52 -0400225 using iterator_category = std::forward_iterator_tag;
226 using value_type = const Range;
227 using difference_type = std::ptrdiff_t;
228 using pointer = value_type*;
229 using reference = value_type&;
230
Junxiao Shib80e9472016-07-20 13:45:24 +0000231 const_iterator() = default;
232
233 const_iterator(ExcludeMap::const_reverse_iterator it, ExcludeMap::const_reverse_iterator rend);
234
Davide Pesaventodb4da5e2018-06-15 11:37:52 -0400235 reference
Junxiao Shib80e9472016-07-20 13:45:24 +0000236 operator*() const;
237
Davide Pesaventodb4da5e2018-06-15 11:37:52 -0400238 pointer
Junxiao Shib80e9472016-07-20 13:45:24 +0000239 operator->() const;
240
241 const_iterator&
242 operator++();
243
244 const_iterator
245 operator++(int);
246
247 bool
248 operator==(const const_iterator& other) const;
249
250 bool
251 operator!=(const const_iterator& other) const;
252
253 private:
254 void
255 update();
256
257 private:
258 ExcludeMap::const_reverse_iterator m_it;
259 ExcludeMap::const_reverse_iterator m_rend;
260 Range m_range;
261 friend class Exclude;
262 };
263
Junxiao Shi75203022014-09-11 10:01:50 -0700264 const_iterator
Alexander Afanasyevff2d08f2014-04-07 18:28:25 -0700265 begin() const;
Alexander Afanasyevb3a6af42014-01-03 13:08:28 -0800266
Junxiao Shi75203022014-09-11 10:01:50 -0700267 const_iterator
Alexander Afanasyevff2d08f2014-04-07 18:28:25 -0700268 end() const;
Alexander Afanasyevb3a6af42014-01-03 13:08:28 -0800269
Junxiao Shib80e9472016-07-20 13:45:24 +0000270 bool
271 empty() const;
272
273 size_t
274 size() const;
275
276 /// \todo const_iterator erase(const_iterator i);
277
278 void
279 clear();
280
Alexander Afanasyevb3a6af42014-01-03 13:08:28 -0800281private:
Junxiao Shidf4b24e2016-07-14 21:41:43 +0000282 /**
283 * @brief directly append exclude element
284 * @tparam T either name::Component or bool
285 *
286 * This method is used during conversion from wire format of exclude filter
287 */
288 template<typename T>
289 void
290 appendEntry(const T& component, bool hasAny);
291
Alexander Afanasyevff2d08f2014-04-07 18:28:25 -0700292 Exclude&
Junxiao Shidf4b24e2016-07-14 21:41:43 +0000293 excludeRange(const ExcludeComponent& from, const name::Component& to);
Alexander Afanasyevb3a6af42014-01-03 13:08:28 -0800294
295private:
Junxiao Shib80e9472016-07-20 13:45:24 +0000296 ExcludeMap m_entries;
Alexander Afanasyevff2d08f2014-04-07 18:28:25 -0700297 mutable Block m_wire;
Junxiao Shib80e9472016-07-20 13:45:24 +0000298
299 friend std::ostream&
300 operator<<(std::ostream& os, const Exclude& name);
Alexander Afanasyevb3a6af42014-01-03 13:08:28 -0800301};
302
Davide Pesavento88a0d812017-08-19 21:31:42 -0400303NDN_CXX_DECLARE_WIRE_ENCODE_INSTANTIATIONS(Exclude);
Alexander Afanasyevb3a6af42014-01-03 13:08:28 -0800304
Junxiao Shidf4b24e2016-07-14 21:41:43 +0000305bool
Junxiao Shib80e9472016-07-20 13:45:24 +0000306operator==(const Exclude::ExcludeComponent& a, const Exclude::ExcludeComponent& b);
307
308bool
Junxiao Shidf4b24e2016-07-14 21:41:43 +0000309operator>(const Exclude::ExcludeComponent& a, const Exclude::ExcludeComponent& b);
Alexander Afanasyev993a0e12014-01-03 13:51:37 -0800310
Junxiao Shib80e9472016-07-20 13:45:24 +0000311std::ostream&
312operator<<(std::ostream& os, const Exclude::Range& range);
313
Davide Pesavento88a0d812017-08-19 21:31:42 -0400314std::ostream&
315operator<<(std::ostream& os, const Exclude& name);
316
Junxiao Shib80e9472016-07-20 13:45:24 +0000317inline Exclude::const_iterator
318Exclude::begin() const
319{
320 return const_iterator(m_entries.rbegin(), m_entries.rend());
321}
322
323inline Exclude::const_iterator
324Exclude::end() const
325{
326 return const_iterator(m_entries.rend(), m_entries.rend());
327}
328
Alexander Afanasyevb3a6af42014-01-03 13:08:28 -0800329inline bool
Alexander Afanasyevff2d08f2014-04-07 18:28:25 -0700330Exclude::empty() const
Alexander Afanasyevb3a6af42014-01-03 13:08:28 -0800331{
Junxiao Shidf4b24e2016-07-14 21:41:43 +0000332 return m_entries.empty();
Alexander Afanasyev85480842014-01-06 14:46:54 -0800333}
334
Alexander Afanasyevba096052014-09-19 15:36:37 -0700335inline bool
336Exclude::operator!=(const Exclude& other) const
Alexander Afanasyevb3a6af42014-01-03 13:08:28 -0800337{
Alexander Afanasyevba096052014-09-19 15:36:37 -0700338 return !(*this == other);
Alexander Afanasyevb3a6af42014-01-03 13:08:28 -0800339}
340
Junxiao Shib80e9472016-07-20 13:45:24 +0000341inline bool
342Exclude::Range::isSingular() const
343{
344 return !this->fromInfinity && !this->toInfinity && this->from == this->to;
345}
346
347inline bool
348Exclude::Range::operator!=(const Exclude::Range& other) const
349{
350 return !this->operator==(other);
351}
352
Davide Pesaventodb4da5e2018-06-15 11:37:52 -0400353inline Exclude::const_iterator::reference
Junxiao Shib80e9472016-07-20 13:45:24 +0000354Exclude::const_iterator::operator*() const
355{
356 BOOST_ASSERT(m_it != m_rend);
357 return m_range;
358}
359
Davide Pesaventodb4da5e2018-06-15 11:37:52 -0400360inline Exclude::const_iterator::pointer
Junxiao Shib80e9472016-07-20 13:45:24 +0000361Exclude::const_iterator::operator->() const
362{
363 BOOST_ASSERT(m_it != m_rend);
364 return &m_range;
365}
366
367inline bool
368Exclude::const_iterator::operator==(const const_iterator& other) const
369{
370 return m_it == other.m_it;
371}
372
373inline bool
374Exclude::const_iterator::operator!=(const const_iterator& other) const
375{
376 return !this->operator==(other);
377}
378
Junxiao Shidf4b24e2016-07-14 21:41:43 +0000379} // namespace ndn
Alexander Afanasyevb3a6af42014-01-03 13:08:28 -0800380
Junxiao Shi4f756902017-07-18 03:05:02 +0000381#endif // NDN_EXCLUDE_HPP