blob: 4cb77af0e6fef4280de934fdf7c79106b5c8a63a [file] [log] [blame]
Alexander Afanasyev90164962014-03-06 08:29:59 +00001/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil -*- */
2/**
3 * Copyright (c) 2013-2014, Regents of the University of California.
4 * All rights reserved.
5 *
6 * This file is part of ndn-cxx library (NDN C++ library with eXperimental eXtensions).
7 * See AUTHORS.md for complete list of ndn-cxx authors and contributors.
8 *
9 * This file licensed under New BSD License. See COPYING for detailed information about
10 * ndn-cxx library copyright, permissions, and redistribution restrictions.
11 */
12
13#ifndef NDN_INTEREST_FILTER_HPP
14#define NDN_INTEREST_FILTER_HPP
15
16#include "util/regex/regex-pattern-list-matcher.hpp"
17#include "name.hpp"
18
19namespace ndn {
20
21class InterestFilter
22{
23public:
24 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 };
33
34 /**
35 * @brief Create an Interest filter to match Interests by prefix
36 *
37 * This filter will match all Interests, whose name start with the given prefix
38 *
39 * Any Name can be implicitly converted to the InterestFilter.
40 */
41 InterestFilter(const Name& prefix);
42
43 /**
44 * @brief Create an Interest filter to match Interests by prefix URI
45 *
46 * This filter will match all Interests, whose name start with the given prefix
47 *
48 * Any const char* can be implicitly converted to the InterestFilter.
49 */
50 InterestFilter(const char* prefixUri);
51
52 /**
53 * @brief Create an Interest filter to match Interests by prefix URI
54 *
55 * This filter will match all Interests, whose name start with the given prefix
56 *
57 * Any std::string can be implicitly converted to the InterestFilter.
58 */
59 InterestFilter(const std::string& prefixUri);
60
61 /**
62 * @brief Create an Interest filter to match Interest by prefix and regular expression
63 *
64 * This filter will match all Interests, whose name start with the given prefix and
65 * other components of the Interest name match the given regular expression.
66 * For example, the following InterestFilter:
67 *
68 * InterestFilter("/hello", "<world><>+")
69 *
70 * will match all Interests, whose name has prefix `/hello`, which is followed by
71 * component `world` and has at least one more component after it. Examples:
72 *
73 * /hello/world/!
74 * /hello/world/x/y/z
75 *
76 * Note that regular expression will need to match all components (e.g., there is
77 * an implicit heading `^` and trailing `$` symbols in the regular expression).
78 */
79 InterestFilter(const Name& prefix, const std::string& regexFilter);
80
81 /**
82 * @brief Implicit conversion to Name (to provide backwards compatibility for onInterest callback)
83 */
84 operator const Name&() const
85 {
86 if (static_cast<bool>(m_regexFilter)) {
87 throw Error("Please update OnInterest callback to accept const InterestFilter& "
88 "(non-trivial Interest filter is being used)");
89 }
90 return m_prefix;
91 }
92
93 /**
94 * @brief Check if specified name matches the filter
95 */
96 bool
97 doesMatch(const Name& name) const;
98
99 const Name&
100 getPrefix() const
101 {
102 return m_prefix;
103 }
104
105 bool
106 hasRegexFilter() const
107 {
108 return static_cast<bool>(m_regexFilter);
109 }
110
111 const RegexPatternListMatcher&
112 getRegexFilter() const
113 {
114 return *m_regexFilter;
115 }
116
117private:
118 Name m_prefix;
119 shared_ptr<RegexPatternListMatcher> m_regexFilter;
120};
121
122inline
123InterestFilter::InterestFilter(const Name& prefix)
124 : m_prefix(prefix)
125{
126}
127
128inline
129InterestFilter::InterestFilter(const char* prefixUri)
130 : m_prefix(prefixUri)
131{
132}
133
134inline
135InterestFilter::InterestFilter(const std::string& prefixUri)
136 : m_prefix(prefixUri)
137{
138}
139
140inline
141InterestFilter::InterestFilter(const Name& prefix, const std::string& regexFilter)
142 : m_prefix(prefix)
143 , m_regexFilter(new RegexPatternListMatcher(regexFilter, shared_ptr<RegexBackrefManager>()))
144{
145}
146
147inline bool
148InterestFilter::doesMatch(const Name& name) const
149{
150 if (name.size() < m_prefix.size())
151 return false;
152
153 if (hasRegexFilter()) {
154 // perform prefix match and regular expression match for the remaining components
155 bool isMatch = m_prefix.isPrefixOf(name);
156
157 if (!isMatch)
158 return false;
159
160 return m_regexFilter->match(name, m_prefix.size(), name.size() - m_prefix.size());
161 }
162 else {
163 // perform just prefix match
164
165 return m_prefix.isPrefixOf(name);
166 }
167}
168
169inline std::ostream&
170operator<<(std::ostream& os, const InterestFilter& filter)
171{
172 os << filter.getPrefix();
173 if (filter.hasRegexFilter()) {
174 os << "?regex=" << filter.getRegexFilter();
175 }
176 return os;
177}
178
179} // namespace ndn
180
181#endif // NDN_INTEREST_FILTER_HPP