blob: 595f143d731cbab9c8fad4ffbcd0f373873da994 [file] [log] [blame]
Alexander Afanasyevc169a812014-05-20 20:37:29 -04001/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
Alexander Afanasyevdfa52c42014-04-24 21:10:11 -07002/**
Junxiao Shidf4b24e2016-07-14 21:41:43 +00003 * Copyright (c) 2013-2016 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
24#ifndef NDN_EXCLUDE_H
25#define NDN_EXCLUDE_H
26
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:
180 /**
181 * @retval true A single component is excluded
182 * @retval false A range of more than one components are excluded
183 */
184 bool
185 isSingular() const;
Alexander Afanasyevb3a6af42014-01-03 13:08:28 -0800186
Junxiao Shib80e9472016-07-20 13:45:24 +0000187 bool
188 operator==(const Exclude::Range& other) const;
189
190 bool
191 operator!=(const Exclude::Range& other) const;
192
193 public:
194 /**
195 * @brief from negative infinity?
196 */
197 bool fromInfinity;
198
199 /**
200 * @brief from component (inclusive)
201 * @pre valid only if !fromInfinity
202 */
203 name::Component from;
204
205 /**
206 * @brief to positive infinity?
207 */
208 bool toInfinity;
209
210 /**
211 * @brief to component (inclusive)
212 * @pre valid only if !toInfinity
213 */
214 name::Component to;
215 };
216
217 class const_iterator : public std::iterator<std::forward_iterator_tag, const Range>
218 {
219 public:
220 const_iterator() = default;
221
222 const_iterator(ExcludeMap::const_reverse_iterator it, ExcludeMap::const_reverse_iterator rend);
223
224 const Range&
225 operator*() const;
226
227 const Range*
228 operator->() const;
229
230 const_iterator&
231 operator++();
232
233 const_iterator
234 operator++(int);
235
236 bool
237 operator==(const const_iterator& other) const;
238
239 bool
240 operator!=(const const_iterator& other) const;
241
242 private:
243 void
244 update();
245
246 private:
247 ExcludeMap::const_reverse_iterator m_it;
248 ExcludeMap::const_reverse_iterator m_rend;
249 Range m_range;
250 friend class Exclude;
251 };
252
Junxiao Shi75203022014-09-11 10:01:50 -0700253 const_iterator
Alexander Afanasyevff2d08f2014-04-07 18:28:25 -0700254 begin() const;
Alexander Afanasyevb3a6af42014-01-03 13:08:28 -0800255
Junxiao Shi75203022014-09-11 10:01:50 -0700256 const_iterator
Alexander Afanasyevff2d08f2014-04-07 18:28:25 -0700257 end() const;
Alexander Afanasyevb3a6af42014-01-03 13:08:28 -0800258
Junxiao Shib80e9472016-07-20 13:45:24 +0000259 bool
260 empty() const;
261
262 size_t
263 size() const;
264
265 /// \todo const_iterator erase(const_iterator i);
266
267 void
268 clear();
269
Alexander Afanasyevb3a6af42014-01-03 13:08:28 -0800270private:
Junxiao Shidf4b24e2016-07-14 21:41:43 +0000271 /**
272 * @brief directly append exclude element
273 * @tparam T either name::Component or bool
274 *
275 * This method is used during conversion from wire format of exclude filter
276 */
277 template<typename T>
278 void
279 appendEntry(const T& component, bool hasAny);
280
Alexander Afanasyevff2d08f2014-04-07 18:28:25 -0700281 Exclude&
Junxiao Shidf4b24e2016-07-14 21:41:43 +0000282 excludeRange(const ExcludeComponent& from, const name::Component& to);
Alexander Afanasyevb3a6af42014-01-03 13:08:28 -0800283
284private:
Junxiao Shib80e9472016-07-20 13:45:24 +0000285 ExcludeMap m_entries;
Alexander Afanasyevff2d08f2014-04-07 18:28:25 -0700286 mutable Block m_wire;
Junxiao Shib80e9472016-07-20 13:45:24 +0000287
288 friend std::ostream&
289 operator<<(std::ostream& os, const Exclude& name);
Alexander Afanasyevb3a6af42014-01-03 13:08:28 -0800290};
291
292std::ostream&
Alexander Afanasyevff2d08f2014-04-07 18:28:25 -0700293operator<<(std::ostream& os, const Exclude& name);
Alexander Afanasyevb3a6af42014-01-03 13:08:28 -0800294
Junxiao Shidf4b24e2016-07-14 21:41:43 +0000295bool
Junxiao Shib80e9472016-07-20 13:45:24 +0000296operator==(const Exclude::ExcludeComponent& a, const Exclude::ExcludeComponent& b);
297
298bool
Junxiao Shidf4b24e2016-07-14 21:41:43 +0000299operator>(const Exclude::ExcludeComponent& a, const Exclude::ExcludeComponent& b);
Alexander Afanasyev993a0e12014-01-03 13:51:37 -0800300
Junxiao Shib80e9472016-07-20 13:45:24 +0000301std::ostream&
302operator<<(std::ostream& os, const Exclude::Range& range);
303
304inline Exclude::const_iterator
305Exclude::begin() const
306{
307 return const_iterator(m_entries.rbegin(), m_entries.rend());
308}
309
310inline Exclude::const_iterator
311Exclude::end() const
312{
313 return const_iterator(m_entries.rend(), m_entries.rend());
314}
315
Alexander Afanasyevb3a6af42014-01-03 13:08:28 -0800316inline bool
Alexander Afanasyevff2d08f2014-04-07 18:28:25 -0700317Exclude::empty() const
Alexander Afanasyevb3a6af42014-01-03 13:08:28 -0800318{
Junxiao Shidf4b24e2016-07-14 21:41:43 +0000319 return m_entries.empty();
Alexander Afanasyev85480842014-01-06 14:46:54 -0800320}
321
Alexander Afanasyevba096052014-09-19 15:36:37 -0700322inline bool
323Exclude::operator!=(const Exclude& other) const
Alexander Afanasyevb3a6af42014-01-03 13:08:28 -0800324{
Alexander Afanasyevba096052014-09-19 15:36:37 -0700325 return !(*this == other);
Alexander Afanasyevb3a6af42014-01-03 13:08:28 -0800326}
327
Junxiao Shib80e9472016-07-20 13:45:24 +0000328inline bool
329Exclude::Range::isSingular() const
330{
331 return !this->fromInfinity && !this->toInfinity && this->from == this->to;
332}
333
334inline bool
335Exclude::Range::operator!=(const Exclude::Range& other) const
336{
337 return !this->operator==(other);
338}
339
340inline const Exclude::Range&
341Exclude::const_iterator::operator*() const
342{
343 BOOST_ASSERT(m_it != m_rend);
344 return m_range;
345}
346
347inline const Exclude::Range*
348Exclude::const_iterator::operator->() const
349{
350 BOOST_ASSERT(m_it != m_rend);
351 return &m_range;
352}
353
354inline bool
355Exclude::const_iterator::operator==(const const_iterator& other) const
356{
357 return m_it == other.m_it;
358}
359
360inline bool
361Exclude::const_iterator::operator!=(const const_iterator& other) const
362{
363 return !this->operator==(other);
364}
365
Junxiao Shidf4b24e2016-07-14 21:41:43 +0000366} // namespace ndn
Alexander Afanasyevb3a6af42014-01-03 13:08:28 -0800367
368#endif // NDN_EXCLUDE_H