blob: 70b60ba195d449ac8cc8476480967899bc1e6af9 [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/**
Alexander Afanasyevc169a812014-05-20 20:37:29 -04003 * Copyright (c) 2013-2014 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/**
36 * @brief Class to represent Exclude component in NDN interests
37 */
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 Afanasyevc348f832014-02-17 16:35:17 -080051 typedef std::map< name::Component, bool /*any*/, std::greater<name::Component> > exclude_type;
Alexander Afanasyevb3a6af42014-01-03 13:08:28 -080052
53 typedef exclude_type::iterator iterator;
54 typedef exclude_type::const_iterator const_iterator;
55 typedef exclude_type::reverse_iterator reverse_iterator;
56 typedef exclude_type::const_reverse_iterator const_reverse_iterator;
57
58 /**
59 * @brief Default constructor an empty exclude
60 */
Alexander Afanasyevff2d08f2014-04-07 18:28:25 -070061 Exclude();
Alexander Afanasyevb3a6af42014-01-03 13:08:28 -080062
63 /**
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -070064 * @brief Create from wire encoding
65 */
66 explicit
67 Exclude(const Block& wire)
68 {
69 wireDecode(wire);
70 }
71
72 /**
Alexander Afanasyevc348f832014-02-17 16:35:17 -080073 * @brief Fast encoding or block size estimation
74 */
75 template<bool T>
76 inline size_t
Alexander Afanasyevff2d08f2014-04-07 18:28:25 -070077 wireEncode(EncodingImpl<T>& block) const;
78
Alexander Afanasyevc348f832014-02-17 16:35:17 -080079 /**
80 * @brief Encode to a wire format
81 */
82 inline const Block&
83 wireEncode() const;
84
85 /**
86 * @brief Decode from the wire format
87 */
Alexander Afanasyevff2d08f2014-04-07 18:28:25 -070088 inline void
89 wireDecode(const Block& wire);
90
Alexander Afanasyevc348f832014-02-17 16:35:17 -080091 ///////////////////////////////////////////////////////////////////////////////
92
93
94 /**
Alexander Afanasyevb3a6af42014-01-03 13:08:28 -080095 * @brief Check if name component is excluded
96 * @param comp Name component to check against exclude filter
97 */
98 bool
Alexander Afanasyevff2d08f2014-04-07 18:28:25 -070099 isExcluded(const name::Component& comp) const;
Alexander Afanasyevb3a6af42014-01-03 13:08:28 -0800100
101 /**
102 * @brief Exclude specific name component
103 * @param comp component to exclude
104 * @returns *this to allow chaining
105 */
Alexander Afanasyevff2d08f2014-04-07 18:28:25 -0700106 Exclude&
107 excludeOne(const name::Component& comp);
Alexander Afanasyevb3a6af42014-01-03 13:08:28 -0800108
109 /**
110 * @brief Exclude components from range [from, to]
111 * @param from first element of the range
112 * @param to last element of the range
113 * @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 /**
119 * @brief Exclude all components from range [/, to]
120 * @param to last element of the range
121 * @returns *this to allow chaining
122 */
Alexander Afanasyevff2d08f2014-04-07 18:28:25 -0700123 inline Exclude&
124 excludeBefore(const name::Component& to);
Alexander Afanasyevb3a6af42014-01-03 13:08:28 -0800125
126 /**
127 * @brief Exclude all components from 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
134 /**
135 * @brief Method to directly append exclude element
136 * @param name excluded name component
137 * @param any flag indicating if there is a postfix ANY component after the name
138 *
139 * This method is used during conversion from wire format of exclude filter
140 *
141 * If there is an error with ranges (e.g., order of components is wrong) an exception is thrown
142 */
Alexander Afanasyev993a0e12014-01-03 13:51:37 -0800143 inline void
Alexander Afanasyevff2d08f2014-04-07 18:28:25 -0700144 appendExclude(const name::Component& name, bool any);
Alexander Afanasyevb3a6af42014-01-03 13:08:28 -0800145
146 /**
147 * @brief Check if exclude filter is empty
148 */
149 inline bool
Alexander Afanasyevff2d08f2014-04-07 18:28:25 -0700150 empty() const;
Alexander Afanasyev85480842014-01-06 14:46:54 -0800151
152 /**
153 * @brief Clear the exclude filter
154 */
155 inline void
156 clear();
Alexander Afanasyevff2d08f2014-04-07 18:28:25 -0700157
Alexander Afanasyevb3a6af42014-01-03 13:08:28 -0800158 /**
159 * @brief Get number of exclude terms
160 */
161 inline size_t
Alexander Afanasyevff2d08f2014-04-07 18:28:25 -0700162 size() const;
Alexander Afanasyevb3a6af42014-01-03 13:08:28 -0800163
164 /**
165 * @brief Get begin iterator of the exclude terms
166 */
167 inline const_iterator
Alexander Afanasyevff2d08f2014-04-07 18:28:25 -0700168 begin() const;
Alexander Afanasyevb3a6af42014-01-03 13:08:28 -0800169
170 /**
171 * @brief Get end iterator of the exclude terms
172 */
173 inline const_iterator
Alexander Afanasyevff2d08f2014-04-07 18:28:25 -0700174 end() const;
Alexander Afanasyevb3a6af42014-01-03 13:08:28 -0800175
176 /**
177 * @brief Get begin iterator of the exclude terms
178 */
179 inline const_reverse_iterator
Alexander Afanasyevff2d08f2014-04-07 18:28:25 -0700180 rbegin() const;
Alexander Afanasyevb3a6af42014-01-03 13:08:28 -0800181
182 /**
183 * @brief Get end iterator of the exclude terms
184 */
185 inline const_reverse_iterator
Alexander Afanasyevff2d08f2014-04-07 18:28:25 -0700186 rend() const;
Alexander Afanasyevb3a6af42014-01-03 13:08:28 -0800187
188 /**
189 * @brief Get escaped string representation (e.g., for use in URI) of the exclude filter
190 */
191 inline std::string
Alexander Afanasyevff2d08f2014-04-07 18:28:25 -0700192 toUri() const;
Alexander Afanasyev993a0e12014-01-03 13:51:37 -0800193
Alexander Afanasyevb3a6af42014-01-03 13:08:28 -0800194private:
Alexander Afanasyevff2d08f2014-04-07 18:28:25 -0700195 Exclude&
196 excludeRange(iterator fromLowerBound, iterator toLowerBound);
Alexander Afanasyevb3a6af42014-01-03 13:08:28 -0800197
198private:
199 exclude_type m_exclude;
Alexander Afanasyev993a0e12014-01-03 13:51:37 -0800200
Alexander Afanasyevff2d08f2014-04-07 18:28:25 -0700201 mutable Block m_wire;
Alexander Afanasyevb3a6af42014-01-03 13:08:28 -0800202};
203
204std::ostream&
Alexander Afanasyevff2d08f2014-04-07 18:28:25 -0700205operator<<(std::ostream& os, const Exclude& name);
Alexander Afanasyevb3a6af42014-01-03 13:08:28 -0800206
Alexander Afanasyevff2d08f2014-04-07 18:28:25 -0700207inline Exclude&
208Exclude::excludeBefore(const name::Component& to)
Alexander Afanasyevb3a6af42014-01-03 13:08:28 -0800209{
Alexander Afanasyevff2d08f2014-04-07 18:28:25 -0700210 return excludeRange(name::Component(), to);
Alexander Afanasyevb3a6af42014-01-03 13:08:28 -0800211}
212
Alexander Afanasyev993a0e12014-01-03 13:51:37 -0800213inline void
Alexander Afanasyevff2d08f2014-04-07 18:28:25 -0700214Exclude::appendExclude(const name::Component& name, bool any)
Alexander Afanasyev993a0e12014-01-03 13:51:37 -0800215{
216 m_exclude[name] = any;
217}
218
Alexander Afanasyevb3a6af42014-01-03 13:08:28 -0800219inline bool
Alexander Afanasyevff2d08f2014-04-07 18:28:25 -0700220Exclude::empty() const
Alexander Afanasyevb3a6af42014-01-03 13:08:28 -0800221{
Alexander Afanasyevff2d08f2014-04-07 18:28:25 -0700222 return m_exclude.empty();
Alexander Afanasyevb3a6af42014-01-03 13:08:28 -0800223}
224
Alexander Afanasyev85480842014-01-06 14:46:54 -0800225inline void
Alexander Afanasyevff2d08f2014-04-07 18:28:25 -0700226Exclude::clear()
Alexander Afanasyev85480842014-01-06 14:46:54 -0800227{
Alexander Afanasyevff2d08f2014-04-07 18:28:25 -0700228 m_exclude.clear();
Alexander Afanasyev85480842014-01-06 14:46:54 -0800229}
230
231
Alexander Afanasyevb3a6af42014-01-03 13:08:28 -0800232inline size_t
Alexander Afanasyevff2d08f2014-04-07 18:28:25 -0700233Exclude::size() const
Alexander Afanasyevb3a6af42014-01-03 13:08:28 -0800234{
Alexander Afanasyevff2d08f2014-04-07 18:28:25 -0700235 return m_exclude.size();
Alexander Afanasyevb3a6af42014-01-03 13:08:28 -0800236}
237
238inline Exclude::const_iterator
Alexander Afanasyevff2d08f2014-04-07 18:28:25 -0700239Exclude::begin() const
Alexander Afanasyevb3a6af42014-01-03 13:08:28 -0800240{
Alexander Afanasyevff2d08f2014-04-07 18:28:25 -0700241 return m_exclude.begin();
Alexander Afanasyevb3a6af42014-01-03 13:08:28 -0800242}
243
244inline Exclude::const_iterator
Alexander Afanasyevff2d08f2014-04-07 18:28:25 -0700245Exclude::end() const
Alexander Afanasyevb3a6af42014-01-03 13:08:28 -0800246{
Alexander Afanasyevff2d08f2014-04-07 18:28:25 -0700247 return m_exclude.end();
Alexander Afanasyevb3a6af42014-01-03 13:08:28 -0800248}
249
250inline Exclude::const_reverse_iterator
Alexander Afanasyevff2d08f2014-04-07 18:28:25 -0700251Exclude::rbegin() const
Alexander Afanasyevb3a6af42014-01-03 13:08:28 -0800252{
Alexander Afanasyevff2d08f2014-04-07 18:28:25 -0700253 return m_exclude.rbegin();
Alexander Afanasyevb3a6af42014-01-03 13:08:28 -0800254}
255
256inline Exclude::const_reverse_iterator
Alexander Afanasyevff2d08f2014-04-07 18:28:25 -0700257Exclude::rend() const
Alexander Afanasyevb3a6af42014-01-03 13:08:28 -0800258{
Alexander Afanasyevff2d08f2014-04-07 18:28:25 -0700259 return m_exclude.rend();
Alexander Afanasyevb3a6af42014-01-03 13:08:28 -0800260}
261
262inline std::string
Alexander Afanasyevff2d08f2014-04-07 18:28:25 -0700263Exclude::toUri() const
Alexander Afanasyevb3a6af42014-01-03 13:08:28 -0800264{
265 std::ostringstream os;
266 os << *this;
267 return os.str();
268}
269
Alexander Afanasyevc348f832014-02-17 16:35:17 -0800270template<bool T>
271inline size_t
Alexander Afanasyevff2d08f2014-04-07 18:28:25 -0700272Exclude::wireEncode(EncodingImpl<T>& block) const
Alexander Afanasyevc348f832014-02-17 16:35:17 -0800273{
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -0700274 size_t totalLength = 0;
Alexander Afanasyevc348f832014-02-17 16:35:17 -0800275
276 // Exclude ::= EXCLUDE-TYPE TLV-LENGTH Any? (NameComponent (Any)?)+
277 // Any ::= ANY-TYPE TLV-LENGTH(=0)
Alexander Afanasyevff2d08f2014-04-07 18:28:25 -0700278
279 for (Exclude::const_iterator i = m_exclude.begin(); i != m_exclude.end(); i++)
Alexander Afanasyevc348f832014-02-17 16:35:17 -0800280 {
281 if (i->second)
282 {
Steve DiBenedetto54ce6682014-07-22 13:22:57 -0600283 totalLength += prependBooleanBlock(block, tlv::Any);
Alexander Afanasyevc348f832014-02-17 16:35:17 -0800284 }
285 if (!i->first.empty())
286 {
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -0700287 totalLength += i->first.wireEncode(block);
Alexander Afanasyevc348f832014-02-17 16:35:17 -0800288 }
289 }
290
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -0700291 totalLength += block.prependVarNumber(totalLength);
Steve DiBenedetto54ce6682014-07-22 13:22:57 -0600292 totalLength += block.prependVarNumber(tlv::Exclude);
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -0700293 return totalLength;
Alexander Afanasyevc348f832014-02-17 16:35:17 -0800294}
295
Alexander Afanasyevff2d08f2014-04-07 18:28:25 -0700296inline const Block&
Alexander Afanasyevc348f832014-02-17 16:35:17 -0800297Exclude::wireEncode() const
298{
Alexander Afanasyevff2d08f2014-04-07 18:28:25 -0700299 if (m_wire.hasWire())
300 return m_wire;
Alexander Afanasyevc348f832014-02-17 16:35:17 -0800301
302 EncodingEstimator estimator;
303 size_t estimatedSize = wireEncode(estimator);
Alexander Afanasyevff2d08f2014-04-07 18:28:25 -0700304
Alexander Afanasyevc348f832014-02-17 16:35:17 -0800305 EncodingBuffer buffer(estimatedSize, 0);
306 wireEncode(buffer);
307
Alexander Afanasyevff2d08f2014-04-07 18:28:25 -0700308 m_wire = buffer.block();
309 return m_wire;
Alexander Afanasyevc348f832014-02-17 16:35:17 -0800310}
311
312inline void
Alexander Afanasyevff2d08f2014-04-07 18:28:25 -0700313Exclude::wireDecode(const Block& wire)
Alexander Afanasyevc348f832014-02-17 16:35:17 -0800314{
Alexander Afanasyevff2d08f2014-04-07 18:28:25 -0700315 m_wire = wire;
316 m_wire.parse();
Alexander Afanasyevc348f832014-02-17 16:35:17 -0800317
318 // Exclude ::= EXCLUDE-TYPE TLV-LENGTH Any? (NameComponent (Any)?)+
319 // Any ::= ANY-TYPE TLV-LENGTH(=0)
Alexander Afanasyevff2d08f2014-04-07 18:28:25 -0700320
321 Block::element_const_iterator i = m_wire.elements_begin();
Steve DiBenedetto54ce6682014-07-22 13:22:57 -0600322 if (i->type() == tlv::Any)
Alexander Afanasyevc348f832014-02-17 16:35:17 -0800323 {
324 appendExclude(name::Component(), true);
325 ++i;
326 }
327
Alexander Afanasyevff2d08f2014-04-07 18:28:25 -0700328 while (i != m_wire.elements_end())
Alexander Afanasyevc348f832014-02-17 16:35:17 -0800329 {
Steve DiBenedetto54ce6682014-07-22 13:22:57 -0600330 if (i->type() != tlv::NameComponent)
Alexander Afanasyevc348f832014-02-17 16:35:17 -0800331 throw Error("Incorrect format of Exclude filter");
332
Alexander Afanasyevff2d08f2014-04-07 18:28:25 -0700333 name::Component excludedComponent(i->value(), i->value_size());
Alexander Afanasyevc348f832014-02-17 16:35:17 -0800334 ++i;
335
Alexander Afanasyevff2d08f2014-04-07 18:28:25 -0700336 if (i != m_wire.elements_end())
Alexander Afanasyevc348f832014-02-17 16:35:17 -0800337 {
Steve DiBenedetto54ce6682014-07-22 13:22:57 -0600338 if (i->type() == tlv::Any)
Alexander Afanasyevc348f832014-02-17 16:35:17 -0800339 {
340 appendExclude(excludedComponent, true);
341 ++i;
342 }
343 else
344 {
345 appendExclude(excludedComponent, false);
346 }
347 }
348 else
349 {
350 appendExclude(excludedComponent, false);
351 }
352 }
353}
354
355
Alexander Afanasyevb3a6af42014-01-03 13:08:28 -0800356} // ndn
357
358#endif // NDN_EXCLUDE_H