blob: c38e9f9d5aa409ec6eb5d2c9368a4639eb738630 [file] [log] [blame]
Alexander Afanasyevb3a6af42014-01-03 13:08:28 -08001/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil -*- */
2/*
3 * Copyright (c) 2013, Regents of the University of California
4 * Alexander Afanasyev
5 *
6 * BSD license, See the LICENSE file for more information
7 *
8 * Author: Alexander Afanasyev <alexander.afanasyev@ucla.edu>
9 */
10
11#ifndef NDN_EXCLUDE_H
12#define NDN_EXCLUDE_H
13
Alexander Afanasyevc348f832014-02-17 16:35:17 -080014#include "name-component.hpp"
Alexander Afanasyevb3a6af42014-01-03 13:08:28 -080015
Alexander Afanasyevb3a6af42014-01-03 13:08:28 -080016namespace ndn {
17
Alexander Afanasyevb3a6af42014-01-03 13:08:28 -080018/**
19 * @brief Class to represent Exclude component in NDN interests
20 */
21class Exclude
22{
23public:
Alexander Afanasyevff2d08f2014-04-07 18:28:25 -070024 class Error : public std::runtime_error
25 {
26 public:
27 explicit
28 Error(const std::string& what)
29 : std::runtime_error(what)
30 {
31 }
32 };
Alexander Afanasyev993a0e12014-01-03 13:51:37 -080033
Alexander Afanasyevc348f832014-02-17 16:35:17 -080034 typedef std::map< name::Component, bool /*any*/, std::greater<name::Component> > exclude_type;
Alexander Afanasyevb3a6af42014-01-03 13:08:28 -080035
36 typedef exclude_type::iterator iterator;
37 typedef exclude_type::const_iterator const_iterator;
38 typedef exclude_type::reverse_iterator reverse_iterator;
39 typedef exclude_type::const_reverse_iterator const_reverse_iterator;
40
41 /**
42 * @brief Default constructor an empty exclude
43 */
Alexander Afanasyevff2d08f2014-04-07 18:28:25 -070044 Exclude();
Alexander Afanasyevb3a6af42014-01-03 13:08:28 -080045
46 /**
Alexander Afanasyevc348f832014-02-17 16:35:17 -080047 * @brief Fast encoding or block size estimation
48 */
49 template<bool T>
50 inline size_t
Alexander Afanasyevff2d08f2014-04-07 18:28:25 -070051 wireEncode(EncodingImpl<T>& block) const;
52
Alexander Afanasyevc348f832014-02-17 16:35:17 -080053 /**
54 * @brief Encode to a wire format
55 */
56 inline const Block&
57 wireEncode() const;
58
59 /**
60 * @brief Decode from the wire format
61 */
Alexander Afanasyevff2d08f2014-04-07 18:28:25 -070062 inline void
63 wireDecode(const Block& wire);
64
Alexander Afanasyevc348f832014-02-17 16:35:17 -080065 ///////////////////////////////////////////////////////////////////////////////
66
67
68 /**
Alexander Afanasyevb3a6af42014-01-03 13:08:28 -080069 * @brief Check if name component is excluded
70 * @param comp Name component to check against exclude filter
71 */
72 bool
Alexander Afanasyevff2d08f2014-04-07 18:28:25 -070073 isExcluded(const name::Component& comp) const;
Alexander Afanasyevb3a6af42014-01-03 13:08:28 -080074
75 /**
76 * @brief Exclude specific name component
77 * @param comp component to exclude
78 * @returns *this to allow chaining
79 */
Alexander Afanasyevff2d08f2014-04-07 18:28:25 -070080 Exclude&
81 excludeOne(const name::Component& comp);
Alexander Afanasyevb3a6af42014-01-03 13:08:28 -080082
83 /**
84 * @brief Exclude components from range [from, to]
85 * @param from first element of the range
86 * @param to last element of the range
87 * @returns *this to allow chaining
88 */
Alexander Afanasyevff2d08f2014-04-07 18:28:25 -070089 Exclude&
90 excludeRange(const name::Component& from, const name::Component& to);
Alexander Afanasyevb3a6af42014-01-03 13:08:28 -080091
92 /**
93 * @brief Exclude all components from range [/, to]
94 * @param to last element of the range
95 * @returns *this to allow chaining
96 */
Alexander Afanasyevff2d08f2014-04-07 18:28:25 -070097 inline Exclude&
98 excludeBefore(const name::Component& to);
Alexander Afanasyevb3a6af42014-01-03 13:08:28 -080099
100 /**
101 * @brief Exclude all components from range [from, +Inf]
102 * @param to last element of the range
103 * @returns *this to allow chaining
104 */
Alexander Afanasyevff2d08f2014-04-07 18:28:25 -0700105 Exclude&
106 excludeAfter(const name::Component& from);
Alexander Afanasyevb3a6af42014-01-03 13:08:28 -0800107
108 /**
109 * @brief Method to directly append exclude element
110 * @param name excluded name component
111 * @param any flag indicating if there is a postfix ANY component after the name
112 *
113 * This method is used during conversion from wire format of exclude filter
114 *
115 * If there is an error with ranges (e.g., order of components is wrong) an exception is thrown
116 */
Alexander Afanasyev993a0e12014-01-03 13:51:37 -0800117 inline void
Alexander Afanasyevff2d08f2014-04-07 18:28:25 -0700118 appendExclude(const name::Component& name, bool any);
Alexander Afanasyevb3a6af42014-01-03 13:08:28 -0800119
120 /**
121 * @brief Check if exclude filter is empty
122 */
123 inline bool
Alexander Afanasyevff2d08f2014-04-07 18:28:25 -0700124 empty() const;
Alexander Afanasyev85480842014-01-06 14:46:54 -0800125
126 /**
127 * @brief Clear the exclude filter
128 */
129 inline void
130 clear();
Alexander Afanasyevff2d08f2014-04-07 18:28:25 -0700131
Alexander Afanasyevb3a6af42014-01-03 13:08:28 -0800132 /**
133 * @brief Get number of exclude terms
134 */
135 inline size_t
Alexander Afanasyevff2d08f2014-04-07 18:28:25 -0700136 size() const;
Alexander Afanasyevb3a6af42014-01-03 13:08:28 -0800137
138 /**
139 * @brief Get begin iterator of the exclude terms
140 */
141 inline const_iterator
Alexander Afanasyevff2d08f2014-04-07 18:28:25 -0700142 begin() const;
Alexander Afanasyevb3a6af42014-01-03 13:08:28 -0800143
144 /**
145 * @brief Get end iterator of the exclude terms
146 */
147 inline const_iterator
Alexander Afanasyevff2d08f2014-04-07 18:28:25 -0700148 end() const;
Alexander Afanasyevb3a6af42014-01-03 13:08:28 -0800149
150 /**
151 * @brief Get begin iterator of the exclude terms
152 */
153 inline const_reverse_iterator
Alexander Afanasyevff2d08f2014-04-07 18:28:25 -0700154 rbegin() const;
Alexander Afanasyevb3a6af42014-01-03 13:08:28 -0800155
156 /**
157 * @brief Get end iterator of the exclude terms
158 */
159 inline const_reverse_iterator
Alexander Afanasyevff2d08f2014-04-07 18:28:25 -0700160 rend() const;
Alexander Afanasyevb3a6af42014-01-03 13:08:28 -0800161
162 /**
163 * @brief Get escaped string representation (e.g., for use in URI) of the exclude filter
164 */
165 inline std::string
Alexander Afanasyevff2d08f2014-04-07 18:28:25 -0700166 toUri() const;
Alexander Afanasyev993a0e12014-01-03 13:51:37 -0800167
Alexander Afanasyevb3a6af42014-01-03 13:08:28 -0800168private:
Alexander Afanasyevff2d08f2014-04-07 18:28:25 -0700169 Exclude&
170 excludeRange(iterator fromLowerBound, iterator toLowerBound);
Alexander Afanasyevb3a6af42014-01-03 13:08:28 -0800171
172private:
173 exclude_type m_exclude;
Alexander Afanasyev993a0e12014-01-03 13:51:37 -0800174
Alexander Afanasyevff2d08f2014-04-07 18:28:25 -0700175 mutable Block m_wire;
Alexander Afanasyevb3a6af42014-01-03 13:08:28 -0800176};
177
178std::ostream&
Alexander Afanasyevff2d08f2014-04-07 18:28:25 -0700179operator<<(std::ostream& os, const Exclude& name);
Alexander Afanasyevb3a6af42014-01-03 13:08:28 -0800180
Alexander Afanasyevff2d08f2014-04-07 18:28:25 -0700181inline Exclude&
182Exclude::excludeBefore(const name::Component& to)
Alexander Afanasyevb3a6af42014-01-03 13:08:28 -0800183{
Alexander Afanasyevff2d08f2014-04-07 18:28:25 -0700184 return excludeRange(name::Component(), to);
Alexander Afanasyevb3a6af42014-01-03 13:08:28 -0800185}
186
Alexander Afanasyev993a0e12014-01-03 13:51:37 -0800187inline void
Alexander Afanasyevff2d08f2014-04-07 18:28:25 -0700188Exclude::appendExclude(const name::Component& name, bool any)
Alexander Afanasyev993a0e12014-01-03 13:51:37 -0800189{
190 m_exclude[name] = any;
191}
192
Alexander Afanasyevb3a6af42014-01-03 13:08:28 -0800193inline bool
Alexander Afanasyevff2d08f2014-04-07 18:28:25 -0700194Exclude::empty() const
Alexander Afanasyevb3a6af42014-01-03 13:08:28 -0800195{
Alexander Afanasyevff2d08f2014-04-07 18:28:25 -0700196 return m_exclude.empty();
Alexander Afanasyevb3a6af42014-01-03 13:08:28 -0800197}
198
Alexander Afanasyev85480842014-01-06 14:46:54 -0800199inline void
Alexander Afanasyevff2d08f2014-04-07 18:28:25 -0700200Exclude::clear()
Alexander Afanasyev85480842014-01-06 14:46:54 -0800201{
Alexander Afanasyevff2d08f2014-04-07 18:28:25 -0700202 m_exclude.clear();
Alexander Afanasyev85480842014-01-06 14:46:54 -0800203}
204
205
Alexander Afanasyevb3a6af42014-01-03 13:08:28 -0800206inline size_t
Alexander Afanasyevff2d08f2014-04-07 18:28:25 -0700207Exclude::size() const
Alexander Afanasyevb3a6af42014-01-03 13:08:28 -0800208{
Alexander Afanasyevff2d08f2014-04-07 18:28:25 -0700209 return m_exclude.size();
Alexander Afanasyevb3a6af42014-01-03 13:08:28 -0800210}
211
212inline Exclude::const_iterator
Alexander Afanasyevff2d08f2014-04-07 18:28:25 -0700213Exclude::begin() const
Alexander Afanasyevb3a6af42014-01-03 13:08:28 -0800214{
Alexander Afanasyevff2d08f2014-04-07 18:28:25 -0700215 return m_exclude.begin();
Alexander Afanasyevb3a6af42014-01-03 13:08:28 -0800216}
217
218inline Exclude::const_iterator
Alexander Afanasyevff2d08f2014-04-07 18:28:25 -0700219Exclude::end() const
Alexander Afanasyevb3a6af42014-01-03 13:08:28 -0800220{
Alexander Afanasyevff2d08f2014-04-07 18:28:25 -0700221 return m_exclude.end();
Alexander Afanasyevb3a6af42014-01-03 13:08:28 -0800222}
223
224inline Exclude::const_reverse_iterator
Alexander Afanasyevff2d08f2014-04-07 18:28:25 -0700225Exclude::rbegin() const
Alexander Afanasyevb3a6af42014-01-03 13:08:28 -0800226{
Alexander Afanasyevff2d08f2014-04-07 18:28:25 -0700227 return m_exclude.rbegin();
Alexander Afanasyevb3a6af42014-01-03 13:08:28 -0800228}
229
230inline Exclude::const_reverse_iterator
Alexander Afanasyevff2d08f2014-04-07 18:28:25 -0700231Exclude::rend() const
Alexander Afanasyevb3a6af42014-01-03 13:08:28 -0800232{
Alexander Afanasyevff2d08f2014-04-07 18:28:25 -0700233 return m_exclude.rend();
Alexander Afanasyevb3a6af42014-01-03 13:08:28 -0800234}
235
236inline std::string
Alexander Afanasyevff2d08f2014-04-07 18:28:25 -0700237Exclude::toUri() const
Alexander Afanasyevb3a6af42014-01-03 13:08:28 -0800238{
239 std::ostringstream os;
240 os << *this;
241 return os.str();
242}
243
Alexander Afanasyevc348f832014-02-17 16:35:17 -0800244template<bool T>
245inline size_t
Alexander Afanasyevff2d08f2014-04-07 18:28:25 -0700246Exclude::wireEncode(EncodingImpl<T>& block) const
Alexander Afanasyevc348f832014-02-17 16:35:17 -0800247{
248 size_t total_len = 0;
249
250 // Exclude ::= EXCLUDE-TYPE TLV-LENGTH Any? (NameComponent (Any)?)+
251 // Any ::= ANY-TYPE TLV-LENGTH(=0)
Alexander Afanasyevff2d08f2014-04-07 18:28:25 -0700252
253 for (Exclude::const_iterator i = m_exclude.begin(); i != m_exclude.end(); i++)
Alexander Afanasyevc348f832014-02-17 16:35:17 -0800254 {
255 if (i->second)
256 {
257 total_len += prependBooleanBlock(block, Tlv::Any);
258 }
259 if (!i->first.empty())
260 {
261 total_len += i->first.wireEncode(block);
262 }
263 }
264
265 total_len += block.prependVarNumber(total_len);
266 total_len += block.prependVarNumber(Tlv::Exclude);
267 return total_len;
268}
269
Alexander Afanasyevff2d08f2014-04-07 18:28:25 -0700270inline const Block&
Alexander Afanasyevc348f832014-02-17 16:35:17 -0800271Exclude::wireEncode() const
272{
Alexander Afanasyevff2d08f2014-04-07 18:28:25 -0700273 if (m_wire.hasWire())
274 return m_wire;
Alexander Afanasyevc348f832014-02-17 16:35:17 -0800275
276 EncodingEstimator estimator;
277 size_t estimatedSize = wireEncode(estimator);
Alexander Afanasyevff2d08f2014-04-07 18:28:25 -0700278
Alexander Afanasyevc348f832014-02-17 16:35:17 -0800279 EncodingBuffer buffer(estimatedSize, 0);
280 wireEncode(buffer);
281
Alexander Afanasyevff2d08f2014-04-07 18:28:25 -0700282 m_wire = buffer.block();
283 return m_wire;
Alexander Afanasyevc348f832014-02-17 16:35:17 -0800284}
285
286inline void
Alexander Afanasyevff2d08f2014-04-07 18:28:25 -0700287Exclude::wireDecode(const Block& wire)
Alexander Afanasyevc348f832014-02-17 16:35:17 -0800288{
Alexander Afanasyevff2d08f2014-04-07 18:28:25 -0700289 m_wire = wire;
290 m_wire.parse();
Alexander Afanasyevc348f832014-02-17 16:35:17 -0800291
292 // Exclude ::= EXCLUDE-TYPE TLV-LENGTH Any? (NameComponent (Any)?)+
293 // Any ::= ANY-TYPE TLV-LENGTH(=0)
Alexander Afanasyevff2d08f2014-04-07 18:28:25 -0700294
295 Block::element_const_iterator i = m_wire.elements_begin();
Alexander Afanasyevc348f832014-02-17 16:35:17 -0800296 if (i->type() == Tlv::Any)
297 {
298 appendExclude(name::Component(), true);
299 ++i;
300 }
301
Alexander Afanasyevff2d08f2014-04-07 18:28:25 -0700302 while (i != m_wire.elements_end())
Alexander Afanasyevc348f832014-02-17 16:35:17 -0800303 {
304 if (i->type() != Tlv::NameComponent)
305 throw Error("Incorrect format of Exclude filter");
306
Alexander Afanasyevff2d08f2014-04-07 18:28:25 -0700307 name::Component excludedComponent(i->value(), i->value_size());
Alexander Afanasyevc348f832014-02-17 16:35:17 -0800308 ++i;
309
Alexander Afanasyevff2d08f2014-04-07 18:28:25 -0700310 if (i != m_wire.elements_end())
Alexander Afanasyevc348f832014-02-17 16:35:17 -0800311 {
312 if (i->type() == Tlv::Any)
313 {
314 appendExclude(excludedComponent, true);
315 ++i;
316 }
317 else
318 {
319 appendExclude(excludedComponent, false);
320 }
321 }
322 else
323 {
324 appendExclude(excludedComponent, false);
325 }
326 }
327}
328
329
Alexander Afanasyevb3a6af42014-01-03 13:08:28 -0800330} // ndn
331
332#endif // NDN_EXCLUDE_H