blob: 64eb653476139ba6aa3b39d939badee4dd7ab371 [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 Afanasyevb3a6af42014-01-03 13:08:28 -080028
Alexander Afanasyev258ec2b2014-05-14 16:15:37 -070029#include <map>
30
Alexander Afanasyevb3a6af42014-01-03 13:08:28 -080031namespace ndn {
32
Alexander Afanasyevb3a6af42014-01-03 13:08:28 -080033/**
34 * @brief Class to represent Exclude component in NDN interests
35 */
36class Exclude
37{
38public:
Steve DiBenedetto54ce6682014-07-22 13:22:57 -060039 class Error : public tlv::Error
Alexander Afanasyevff2d08f2014-04-07 18:28:25 -070040 {
41 public:
42 explicit
43 Error(const std::string& what)
Steve DiBenedetto54ce6682014-07-22 13:22:57 -060044 : tlv::Error(what)
Alexander Afanasyevff2d08f2014-04-07 18:28:25 -070045 {
46 }
47 };
Alexander Afanasyev993a0e12014-01-03 13:51:37 -080048
Alexander Afanasyevc348f832014-02-17 16:35:17 -080049 typedef std::map< name::Component, bool /*any*/, std::greater<name::Component> > exclude_type;
Alexander Afanasyevb3a6af42014-01-03 13:08:28 -080050
51 typedef exclude_type::iterator iterator;
52 typedef exclude_type::const_iterator const_iterator;
53 typedef exclude_type::reverse_iterator reverse_iterator;
54 typedef exclude_type::const_reverse_iterator const_reverse_iterator;
55
56 /**
57 * @brief Default constructor an empty exclude
58 */
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
65 Exclude(const Block& wire)
66 {
67 wireDecode(wire);
68 }
69
70 /**
Alexander Afanasyevc348f832014-02-17 16:35:17 -080071 * @brief Fast encoding or block size estimation
72 */
73 template<bool T>
74 inline size_t
Alexander Afanasyevff2d08f2014-04-07 18:28:25 -070075 wireEncode(EncodingImpl<T>& block) const;
76
Alexander Afanasyevc348f832014-02-17 16:35:17 -080077 /**
78 * @brief Encode to a wire format
79 */
80 inline const Block&
81 wireEncode() const;
82
83 /**
84 * @brief Decode from the wire format
85 */
Alexander Afanasyevff2d08f2014-04-07 18:28:25 -070086 inline void
87 wireDecode(const Block& wire);
88
Alexander Afanasyevc348f832014-02-17 16:35:17 -080089 ///////////////////////////////////////////////////////////////////////////////
90
91
92 /**
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 /**
108 * @brief Exclude components from range [from, to]
109 * @param from first element of the range
110 * @param to last element of the range
111 * @returns *this to allow chaining
112 */
Alexander Afanasyevff2d08f2014-04-07 18:28:25 -0700113 Exclude&
114 excludeRange(const name::Component& from, const name::Component& to);
Alexander Afanasyevb3a6af42014-01-03 13:08:28 -0800115
116 /**
117 * @brief Exclude all components from range [/, to]
118 * @param to last element of the range
119 * @returns *this to allow chaining
120 */
Alexander Afanasyevff2d08f2014-04-07 18:28:25 -0700121 inline Exclude&
122 excludeBefore(const name::Component& to);
Alexander Afanasyevb3a6af42014-01-03 13:08:28 -0800123
124 /**
125 * @brief Exclude all components from range [from, +Inf]
Alexander Afanasyev770827c2014-05-13 17:42:55 -0700126 * @param from the first element of the range
Alexander Afanasyevb3a6af42014-01-03 13:08:28 -0800127 * @returns *this to allow chaining
128 */
Alexander Afanasyevff2d08f2014-04-07 18:28:25 -0700129 Exclude&
130 excludeAfter(const name::Component& from);
Alexander Afanasyevb3a6af42014-01-03 13:08:28 -0800131
132 /**
133 * @brief Method to directly append exclude element
134 * @param name excluded name component
135 * @param any flag indicating if there is a postfix ANY component after the name
136 *
137 * This method is used during conversion from wire format of exclude filter
138 *
139 * If there is an error with ranges (e.g., order of components is wrong) an exception is thrown
140 */
Alexander Afanasyev993a0e12014-01-03 13:51:37 -0800141 inline void
Alexander Afanasyevff2d08f2014-04-07 18:28:25 -0700142 appendExclude(const name::Component& name, bool any);
Alexander Afanasyevb3a6af42014-01-03 13:08:28 -0800143
144 /**
145 * @brief Check if exclude filter is empty
146 */
147 inline bool
Alexander Afanasyevff2d08f2014-04-07 18:28:25 -0700148 empty() const;
Alexander Afanasyev85480842014-01-06 14:46:54 -0800149
150 /**
151 * @brief Clear the exclude filter
152 */
153 inline void
154 clear();
Alexander Afanasyevff2d08f2014-04-07 18:28:25 -0700155
Alexander Afanasyevb3a6af42014-01-03 13:08:28 -0800156 /**
157 * @brief Get number of exclude terms
158 */
159 inline size_t
Alexander Afanasyevff2d08f2014-04-07 18:28:25 -0700160 size() const;
Alexander Afanasyevb3a6af42014-01-03 13:08:28 -0800161
162 /**
163 * @brief Get begin iterator of the exclude terms
164 */
165 inline const_iterator
Alexander Afanasyevff2d08f2014-04-07 18:28:25 -0700166 begin() const;
Alexander Afanasyevb3a6af42014-01-03 13:08:28 -0800167
168 /**
169 * @brief Get end iterator of the exclude terms
170 */
171 inline const_iterator
Alexander Afanasyevff2d08f2014-04-07 18:28:25 -0700172 end() const;
Alexander Afanasyevb3a6af42014-01-03 13:08:28 -0800173
174 /**
175 * @brief Get begin iterator of the exclude terms
176 */
177 inline const_reverse_iterator
Alexander Afanasyevff2d08f2014-04-07 18:28:25 -0700178 rbegin() const;
Alexander Afanasyevb3a6af42014-01-03 13:08:28 -0800179
180 /**
181 * @brief Get end iterator of the exclude terms
182 */
183 inline const_reverse_iterator
Alexander Afanasyevff2d08f2014-04-07 18:28:25 -0700184 rend() const;
Alexander Afanasyevb3a6af42014-01-03 13:08:28 -0800185
186 /**
187 * @brief Get escaped string representation (e.g., for use in URI) of the exclude filter
188 */
189 inline std::string
Alexander Afanasyevff2d08f2014-04-07 18:28:25 -0700190 toUri() const;
Alexander Afanasyev993a0e12014-01-03 13:51:37 -0800191
Alexander Afanasyevb3a6af42014-01-03 13:08:28 -0800192private:
Alexander Afanasyevff2d08f2014-04-07 18:28:25 -0700193 Exclude&
194 excludeRange(iterator fromLowerBound, iterator toLowerBound);
Alexander Afanasyevb3a6af42014-01-03 13:08:28 -0800195
196private:
197 exclude_type m_exclude;
Alexander Afanasyev993a0e12014-01-03 13:51:37 -0800198
Alexander Afanasyevff2d08f2014-04-07 18:28:25 -0700199 mutable Block m_wire;
Alexander Afanasyevb3a6af42014-01-03 13:08:28 -0800200};
201
202std::ostream&
Alexander Afanasyevff2d08f2014-04-07 18:28:25 -0700203operator<<(std::ostream& os, const Exclude& name);
Alexander Afanasyevb3a6af42014-01-03 13:08:28 -0800204
Alexander Afanasyevff2d08f2014-04-07 18:28:25 -0700205inline Exclude&
206Exclude::excludeBefore(const name::Component& to)
Alexander Afanasyevb3a6af42014-01-03 13:08:28 -0800207{
Alexander Afanasyevff2d08f2014-04-07 18:28:25 -0700208 return excludeRange(name::Component(), to);
Alexander Afanasyevb3a6af42014-01-03 13:08:28 -0800209}
210
Alexander Afanasyev993a0e12014-01-03 13:51:37 -0800211inline void
Alexander Afanasyevff2d08f2014-04-07 18:28:25 -0700212Exclude::appendExclude(const name::Component& name, bool any)
Alexander Afanasyev993a0e12014-01-03 13:51:37 -0800213{
214 m_exclude[name] = any;
215}
216
Alexander Afanasyevb3a6af42014-01-03 13:08:28 -0800217inline bool
Alexander Afanasyevff2d08f2014-04-07 18:28:25 -0700218Exclude::empty() const
Alexander Afanasyevb3a6af42014-01-03 13:08:28 -0800219{
Alexander Afanasyevff2d08f2014-04-07 18:28:25 -0700220 return m_exclude.empty();
Alexander Afanasyevb3a6af42014-01-03 13:08:28 -0800221}
222
Alexander Afanasyev85480842014-01-06 14:46:54 -0800223inline void
Alexander Afanasyevff2d08f2014-04-07 18:28:25 -0700224Exclude::clear()
Alexander Afanasyev85480842014-01-06 14:46:54 -0800225{
Alexander Afanasyevff2d08f2014-04-07 18:28:25 -0700226 m_exclude.clear();
Alexander Afanasyev85480842014-01-06 14:46:54 -0800227}
228
229
Alexander Afanasyevb3a6af42014-01-03 13:08:28 -0800230inline size_t
Alexander Afanasyevff2d08f2014-04-07 18:28:25 -0700231Exclude::size() const
Alexander Afanasyevb3a6af42014-01-03 13:08:28 -0800232{
Alexander Afanasyevff2d08f2014-04-07 18:28:25 -0700233 return m_exclude.size();
Alexander Afanasyevb3a6af42014-01-03 13:08:28 -0800234}
235
236inline Exclude::const_iterator
Alexander Afanasyevff2d08f2014-04-07 18:28:25 -0700237Exclude::begin() const
Alexander Afanasyevb3a6af42014-01-03 13:08:28 -0800238{
Alexander Afanasyevff2d08f2014-04-07 18:28:25 -0700239 return m_exclude.begin();
Alexander Afanasyevb3a6af42014-01-03 13:08:28 -0800240}
241
242inline Exclude::const_iterator
Alexander Afanasyevff2d08f2014-04-07 18:28:25 -0700243Exclude::end() const
Alexander Afanasyevb3a6af42014-01-03 13:08:28 -0800244{
Alexander Afanasyevff2d08f2014-04-07 18:28:25 -0700245 return m_exclude.end();
Alexander Afanasyevb3a6af42014-01-03 13:08:28 -0800246}
247
248inline Exclude::const_reverse_iterator
Alexander Afanasyevff2d08f2014-04-07 18:28:25 -0700249Exclude::rbegin() const
Alexander Afanasyevb3a6af42014-01-03 13:08:28 -0800250{
Alexander Afanasyevff2d08f2014-04-07 18:28:25 -0700251 return m_exclude.rbegin();
Alexander Afanasyevb3a6af42014-01-03 13:08:28 -0800252}
253
254inline Exclude::const_reverse_iterator
Alexander Afanasyevff2d08f2014-04-07 18:28:25 -0700255Exclude::rend() const
Alexander Afanasyevb3a6af42014-01-03 13:08:28 -0800256{
Alexander Afanasyevff2d08f2014-04-07 18:28:25 -0700257 return m_exclude.rend();
Alexander Afanasyevb3a6af42014-01-03 13:08:28 -0800258}
259
260inline std::string
Alexander Afanasyevff2d08f2014-04-07 18:28:25 -0700261Exclude::toUri() const
Alexander Afanasyevb3a6af42014-01-03 13:08:28 -0800262{
263 std::ostringstream os;
264 os << *this;
265 return os.str();
266}
267
Alexander Afanasyevc348f832014-02-17 16:35:17 -0800268template<bool T>
269inline size_t
Alexander Afanasyevff2d08f2014-04-07 18:28:25 -0700270Exclude::wireEncode(EncodingImpl<T>& block) const
Alexander Afanasyevc348f832014-02-17 16:35:17 -0800271{
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -0700272 size_t totalLength = 0;
Alexander Afanasyevc348f832014-02-17 16:35:17 -0800273
274 // Exclude ::= EXCLUDE-TYPE TLV-LENGTH Any? (NameComponent (Any)?)+
275 // Any ::= ANY-TYPE TLV-LENGTH(=0)
Alexander Afanasyevff2d08f2014-04-07 18:28:25 -0700276
277 for (Exclude::const_iterator i = m_exclude.begin(); i != m_exclude.end(); i++)
Alexander Afanasyevc348f832014-02-17 16:35:17 -0800278 {
279 if (i->second)
280 {
Steve DiBenedetto54ce6682014-07-22 13:22:57 -0600281 totalLength += prependBooleanBlock(block, tlv::Any);
Alexander Afanasyevc348f832014-02-17 16:35:17 -0800282 }
283 if (!i->first.empty())
284 {
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -0700285 totalLength += i->first.wireEncode(block);
Alexander Afanasyevc348f832014-02-17 16:35:17 -0800286 }
287 }
288
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -0700289 totalLength += block.prependVarNumber(totalLength);
Steve DiBenedetto54ce6682014-07-22 13:22:57 -0600290 totalLength += block.prependVarNumber(tlv::Exclude);
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -0700291 return totalLength;
Alexander Afanasyevc348f832014-02-17 16:35:17 -0800292}
293
Alexander Afanasyevff2d08f2014-04-07 18:28:25 -0700294inline const Block&
Alexander Afanasyevc348f832014-02-17 16:35:17 -0800295Exclude::wireEncode() const
296{
Alexander Afanasyevff2d08f2014-04-07 18:28:25 -0700297 if (m_wire.hasWire())
298 return m_wire;
Alexander Afanasyevc348f832014-02-17 16:35:17 -0800299
300 EncodingEstimator estimator;
301 size_t estimatedSize = wireEncode(estimator);
Alexander Afanasyevff2d08f2014-04-07 18:28:25 -0700302
Alexander Afanasyevc348f832014-02-17 16:35:17 -0800303 EncodingBuffer buffer(estimatedSize, 0);
304 wireEncode(buffer);
305
Alexander Afanasyevff2d08f2014-04-07 18:28:25 -0700306 m_wire = buffer.block();
307 return m_wire;
Alexander Afanasyevc348f832014-02-17 16:35:17 -0800308}
309
310inline void
Alexander Afanasyevff2d08f2014-04-07 18:28:25 -0700311Exclude::wireDecode(const Block& wire)
Alexander Afanasyevc348f832014-02-17 16:35:17 -0800312{
Alexander Afanasyevff2d08f2014-04-07 18:28:25 -0700313 m_wire = wire;
314 m_wire.parse();
Alexander Afanasyevc348f832014-02-17 16:35:17 -0800315
316 // Exclude ::= EXCLUDE-TYPE TLV-LENGTH Any? (NameComponent (Any)?)+
317 // Any ::= ANY-TYPE TLV-LENGTH(=0)
Alexander Afanasyevff2d08f2014-04-07 18:28:25 -0700318
319 Block::element_const_iterator i = m_wire.elements_begin();
Steve DiBenedetto54ce6682014-07-22 13:22:57 -0600320 if (i->type() == tlv::Any)
Alexander Afanasyevc348f832014-02-17 16:35:17 -0800321 {
322 appendExclude(name::Component(), true);
323 ++i;
324 }
325
Alexander Afanasyevff2d08f2014-04-07 18:28:25 -0700326 while (i != m_wire.elements_end())
Alexander Afanasyevc348f832014-02-17 16:35:17 -0800327 {
Steve DiBenedetto54ce6682014-07-22 13:22:57 -0600328 if (i->type() != tlv::NameComponent)
Alexander Afanasyevc348f832014-02-17 16:35:17 -0800329 throw Error("Incorrect format of Exclude filter");
330
Alexander Afanasyevff2d08f2014-04-07 18:28:25 -0700331 name::Component excludedComponent(i->value(), i->value_size());
Alexander Afanasyevc348f832014-02-17 16:35:17 -0800332 ++i;
333
Alexander Afanasyevff2d08f2014-04-07 18:28:25 -0700334 if (i != m_wire.elements_end())
Alexander Afanasyevc348f832014-02-17 16:35:17 -0800335 {
Steve DiBenedetto54ce6682014-07-22 13:22:57 -0600336 if (i->type() == tlv::Any)
Alexander Afanasyevc348f832014-02-17 16:35:17 -0800337 {
338 appendExclude(excludedComponent, true);
339 ++i;
340 }
341 else
342 {
343 appendExclude(excludedComponent, false);
344 }
345 }
346 else
347 {
348 appendExclude(excludedComponent, false);
349 }
350 }
351}
352
353
Alexander Afanasyevb3a6af42014-01-03 13:08:28 -0800354} // ndn
355
356#endif // NDN_EXCLUDE_H