blob: 7bf5a5e20ea9f9d4c1ab4c6890af495f8e17884c [file] [log] [blame]
Alexander Afanasyevc169a812014-05-20 20:37:29 -04001/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
Yingdi Yu5e974202014-01-29 16:59:06 -08002/**
Alexander Afanasyev73e30042015-09-17 17:09:51 -07003 * Copyright (c) 2013-2015 Regents of the University of California.
Alexander Afanasyevdfa52c42014-04-24 21:10:11 -07004 *
5 * This file is part of ndn-cxx library (NDN C++ library with eXperimental eXtensions).
Alexander Afanasyevdfa52c42014-04-24 21:10:11 -07006 *
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 Yingdi Yu <http://irl.cs.ucla.edu/~yingdi/>
Yingdi Yu5e974202014-01-29 16:59:06 -080022 */
23
Alexander Afanasyev36b84cf2014-02-17 19:34:18 -080024#ifndef NDN_UTIL_REGEX_COMPONENT_SET_MATCHER_HPP
25#define NDN_UTIL_REGEX_COMPONENT_SET_MATCHER_HPP
Yingdi Yu5e974202014-01-29 16:59:06 -080026
Alexander Afanasyev36b84cf2014-02-17 19:34:18 -080027#include "../../common.hpp"
Yingdi Yu5e974202014-01-29 16:59:06 -080028
29#include "regex-matcher.hpp"
30#include "regex-component-matcher.hpp"
31
Alexander Afanasyev258ec2b2014-05-14 16:15:37 -070032#include <set>
33
Alexander Afanasyev36b84cf2014-02-17 19:34:18 -080034namespace ndn {
Yingdi Yu5e974202014-01-29 16:59:06 -080035
Alexander Afanasyev2a7f7202014-04-23 14:25:29 -070036class RegexComponentSetMatcher : public RegexMatcher
37{
Yingdi Yu5e974202014-01-29 16:59:06 -080038public:
39 /**
40 * @brief Create a RegexComponentSetMatcher matcher from expr
41 * @param expr The standard regular expression to match a component
Alexander Afanasyevb6b21b32014-04-28 22:38:03 -070042 * @param backrefManager Shared pointer to back-reference manager
Yingdi Yu5e974202014-01-29 16:59:06 -080043 */
Alexander Afanasyevb6b21b32014-04-28 22:38:03 -070044 RegexComponentSetMatcher(const std::string& expr, shared_ptr<RegexBackrefManager> backrefManager);
Yingdi Yu5e974202014-01-29 16:59:06 -080045
Alexander Afanasyevb6b21b32014-04-28 22:38:03 -070046 virtual
47 ~RegexComponentSetMatcher();
Yingdi Yu5e974202014-01-29 16:59:06 -080048
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -070049 virtual bool
Alexander Afanasyevb6b21b32014-04-28 22:38:03 -070050 match(const Name& name, size_t offset, size_t len = 1);
Yingdi Yu5e974202014-01-29 16:59:06 -080051
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -070052protected:
Yingdi Yu5e974202014-01-29 16:59:06 -080053 /**
54 * @brief Compile the regular expression to generate the more matchers when necessary
Yingdi Yu5e974202014-01-29 16:59:06 -080055 */
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -070056 virtual void
Yingdi Yu5e974202014-01-29 16:59:06 -080057 compile();
58
59private:
Alexander Afanasyevb6b21b32014-04-28 22:38:03 -070060 size_t
61 extractComponent(size_t index);
Yingdi Yu5e974202014-01-29 16:59:06 -080062
63 void
64 compileSingleComponent();
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -070065
Yingdi Yu5e974202014-01-29 16:59:06 -080066 void
Alexander Afanasyevb6b21b32014-04-28 22:38:03 -070067 compileMultipleComponents(size_t start, size_t lastIndex);
Yingdi Yu5e974202014-01-29 16:59:06 -080068
69private:
Alexander Afanasyev36b84cf2014-02-17 19:34:18 -080070 typedef std::set<shared_ptr<RegexComponentMatcher> > ComponentsSet;
71 ComponentsSet m_components;
Alexander Afanasyevb6b21b32014-04-28 22:38:03 -070072 bool m_isInclusion;
Yingdi Yu5e974202014-01-29 16:59:06 -080073};
74
Yingdi Yu5e974202014-01-29 16:59:06 -080075
Alexander Afanasyev36b84cf2014-02-17 19:34:18 -080076inline
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -070077RegexComponentSetMatcher::RegexComponentSetMatcher(const std::string& expr,
Alexander Afanasyevb6b21b32014-04-28 22:38:03 -070078 shared_ptr<RegexBackrefManager> backrefManager)
79 : RegexMatcher(expr, EXPR_COMPONENT_SET, backrefManager)
80 , m_isInclusion(true)
Alexander Afanasyev36b84cf2014-02-17 19:34:18 -080081{
Alexander Afanasyev36b84cf2014-02-17 19:34:18 -080082 compile();
Alexander Afanasyev36b84cf2014-02-17 19:34:18 -080083}
84
85inline
86RegexComponentSetMatcher::~RegexComponentSetMatcher()
87{
Alexander Afanasyev36b84cf2014-02-17 19:34:18 -080088}
89
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -070090inline void
Alexander Afanasyev36b84cf2014-02-17 19:34:18 -080091RegexComponentSetMatcher::compile()
92{
Alexander Afanasyevb6b21b32014-04-28 22:38:03 -070093 if (m_expr.size() < 2)
Spyridon Mastorakis0d2ed2e2015-07-27 19:09:12 -070094 BOOST_THROW_EXCEPTION(RegexMatcher::Error("Regexp compile error (cannot parse " +
95 m_expr + ")"));
Alexander Afanasyevb6b21b32014-04-28 22:38:03 -070096
97 switch (m_expr[0]) {
Alexander Afanasyev36b84cf2014-02-17 19:34:18 -080098 case '<':
99 return compileSingleComponent();
100 case '[':
101 {
Alexander Afanasyevb6b21b32014-04-28 22:38:03 -0700102 size_t lastIndex = m_expr.size() - 1;
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -0700103 if (']' != m_expr[lastIndex])
Spyridon Mastorakis0d2ed2e2015-07-27 19:09:12 -0700104 BOOST_THROW_EXCEPTION(RegexMatcher::Error("Regexp compile error (no matching ']' in " +
105 m_expr + ")"));
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -0700106
Alexander Afanasyevb6b21b32014-04-28 22:38:03 -0700107 if ('^' == m_expr[1]) {
108 m_isInclusion = false;
Alexander Afanasyev36b84cf2014-02-17 19:34:18 -0800109 compileMultipleComponents(2, lastIndex);
110 }
111 else
112 compileMultipleComponents(1, lastIndex);
113 break;
114 }
115 default:
Spyridon Mastorakis0d2ed2e2015-07-27 19:09:12 -0700116 BOOST_THROW_EXCEPTION(RegexMatcher::Error("Regexp compile error (cannot parse " +
117 m_expr + ")"));
Alexander Afanasyev36b84cf2014-02-17 19:34:18 -0800118 }
119}
120
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -0700121inline void
Alexander Afanasyev36b84cf2014-02-17 19:34:18 -0800122RegexComponentSetMatcher::compileSingleComponent()
123{
Alexander Afanasyev1dd95c52014-03-22 19:11:36 -0700124 size_t end = extractComponent(1);
Alexander Afanasyev36b84cf2014-02-17 19:34:18 -0800125
Alexander Afanasyev1dd95c52014-03-22 19:11:36 -0700126 if (m_expr.size() != end)
Alexander Afanasyev36b84cf2014-02-17 19:34:18 -0800127 {
Spyridon Mastorakis0d2ed2e2015-07-27 19:09:12 -0700128 BOOST_THROW_EXCEPTION(RegexMatcher::Error("Component expr error " + m_expr));
Alexander Afanasyev36b84cf2014-02-17 19:34:18 -0800129 }
130 else
131 {
132 shared_ptr<RegexComponentMatcher> component =
133 make_shared<RegexComponentMatcher>(m_expr.substr(1, end - 2), m_backrefManager);
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -0700134
135 m_components.insert(component);
Alexander Afanasyev36b84cf2014-02-17 19:34:18 -0800136 }
137}
138
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -0700139inline void
Alexander Afanasyevb6b21b32014-04-28 22:38:03 -0700140RegexComponentSetMatcher::compileMultipleComponents(size_t start, size_t lastIndex)
Alexander Afanasyev36b84cf2014-02-17 19:34:18 -0800141{
Alexander Afanasyevb6b21b32014-04-28 22:38:03 -0700142 size_t index = start;
143 size_t tempIndex = start;
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -0700144
Alexander Afanasyevb6b21b32014-04-28 22:38:03 -0700145 while (index < lastIndex) {
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -0700146 if ('<' != m_expr[index])
Spyridon Mastorakis0d2ed2e2015-07-27 19:09:12 -0700147 BOOST_THROW_EXCEPTION(RegexMatcher::Error("Component expr error " + m_expr));
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -0700148
Alexander Afanasyevb6b21b32014-04-28 22:38:03 -0700149 tempIndex = index + 1;
150 index = extractComponent(tempIndex);
Alexander Afanasyev36b84cf2014-02-17 19:34:18 -0800151
152 shared_ptr<RegexComponentMatcher> component =
Alexander Afanasyevb6b21b32014-04-28 22:38:03 -0700153 make_shared<RegexComponentMatcher>(m_expr.substr(tempIndex, index - tempIndex - 1),
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -0700154 m_backrefManager);
155
Alexander Afanasyev36b84cf2014-02-17 19:34:18 -0800156 m_components.insert(component);
157 }
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -0700158
159 if (index != lastIndex)
Spyridon Mastorakis0d2ed2e2015-07-27 19:09:12 -0700160 BOOST_THROW_EXCEPTION(RegexMatcher::Error("Not sufficient expr to parse " + m_expr));
Alexander Afanasyev36b84cf2014-02-17 19:34:18 -0800161}
162
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -0700163inline bool
Alexander Afanasyevb6b21b32014-04-28 22:38:03 -0700164RegexComponentSetMatcher::match(const Name& name, size_t offset, size_t len)
Alexander Afanasyev36b84cf2014-02-17 19:34:18 -0800165{
Alexander Afanasyevb6b21b32014-04-28 22:38:03 -0700166 bool isMatched = false;
Alexander Afanasyev36b84cf2014-02-17 19:34:18 -0800167
168 /* componentset only matches one component */
169 if (len != 1)
170 {
171 return false;
172 }
173
174 for (ComponentsSet::iterator it = m_components.begin();
175 it != m_components.end();
176 ++it)
177 {
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -0700178 if ((*it)->match(name, offset, len))
Alexander Afanasyev36b84cf2014-02-17 19:34:18 -0800179 {
Alexander Afanasyevb6b21b32014-04-28 22:38:03 -0700180 isMatched = true;
Alexander Afanasyev36b84cf2014-02-17 19:34:18 -0800181 break;
182 }
183 }
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -0700184
Alexander Afanasyev36b84cf2014-02-17 19:34:18 -0800185 m_matchResult.clear();
186
Alexander Afanasyevb6b21b32014-04-28 22:38:03 -0700187 if (m_isInclusion ? isMatched : !isMatched)
Alexander Afanasyev36b84cf2014-02-17 19:34:18 -0800188 {
189 m_matchResult.push_back(name.get(offset));
190 return true;
191 }
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -0700192 else
Alexander Afanasyev36b84cf2014-02-17 19:34:18 -0800193 return false;
194}
195
Alexander Afanasyevb6b21b32014-04-28 22:38:03 -0700196inline size_t
197RegexComponentSetMatcher::extractComponent(size_t index)
Alexander Afanasyev36b84cf2014-02-17 19:34:18 -0800198{
Alexander Afanasyevb6b21b32014-04-28 22:38:03 -0700199 size_t lcount = 1;
200 size_t rcount = 0;
Alexander Afanasyev36b84cf2014-02-17 19:34:18 -0800201
Alexander Afanasyevb6b21b32014-04-28 22:38:03 -0700202 while (lcount > rcount) {
203 switch (m_expr[index]) {
Alexander Afanasyev36b84cf2014-02-17 19:34:18 -0800204 case '<':
205 lcount++;
206 break;
207
208 case '>':
209 rcount++;
210 break;
211
212 case 0:
Spyridon Mastorakis0d2ed2e2015-07-27 19:09:12 -0700213 BOOST_THROW_EXCEPTION(RegexMatcher::Error("Error: square brackets mismatch"));
Alexander Afanasyev36b84cf2014-02-17 19:34:18 -0800214 break;
215 }
216 index++;
217
218 }
219
220 return index;
221}
222
223} // namespace ndn
224
225#endif // NDN_UTIL_REGEX_COMPONENT_SET_MATCHER_HPP