blob: 9c2ff161d66a76e1196c3c5f295cf55081d5be28 [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 Afanasyevc169a812014-05-20 20:37:29 -04003 * Copyright (c) 2013-2014 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
55 * @returns true if compiling succeeds
56 */
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -070057 virtual void
Yingdi Yu5e974202014-01-29 16:59:06 -080058 compile();
59
60private:
Alexander Afanasyevb6b21b32014-04-28 22:38:03 -070061 size_t
62 extractComponent(size_t index);
Yingdi Yu5e974202014-01-29 16:59:06 -080063
64 void
65 compileSingleComponent();
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -070066
Yingdi Yu5e974202014-01-29 16:59:06 -080067 void
Alexander Afanasyevb6b21b32014-04-28 22:38:03 -070068 compileMultipleComponents(size_t start, size_t lastIndex);
Yingdi Yu5e974202014-01-29 16:59:06 -080069
70private:
Alexander Afanasyev36b84cf2014-02-17 19:34:18 -080071 typedef std::set<shared_ptr<RegexComponentMatcher> > ComponentsSet;
72 ComponentsSet m_components;
Alexander Afanasyevb6b21b32014-04-28 22:38:03 -070073 bool m_isInclusion;
Yingdi Yu5e974202014-01-29 16:59:06 -080074};
75
Yingdi Yu5e974202014-01-29 16:59:06 -080076
Alexander Afanasyev36b84cf2014-02-17 19:34:18 -080077inline
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -070078RegexComponentSetMatcher::RegexComponentSetMatcher(const std::string& expr,
Alexander Afanasyevb6b21b32014-04-28 22:38:03 -070079 shared_ptr<RegexBackrefManager> backrefManager)
80 : RegexMatcher(expr, EXPR_COMPONENT_SET, backrefManager)
81 , m_isInclusion(true)
Alexander Afanasyev36b84cf2014-02-17 19:34:18 -080082{
Alexander Afanasyev36b84cf2014-02-17 19:34:18 -080083 compile();
Alexander Afanasyev36b84cf2014-02-17 19:34:18 -080084}
85
86inline
87RegexComponentSetMatcher::~RegexComponentSetMatcher()
88{
Alexander Afanasyev36b84cf2014-02-17 19:34:18 -080089}
90
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -070091inline void
Alexander Afanasyev36b84cf2014-02-17 19:34:18 -080092RegexComponentSetMatcher::compile()
93{
Alexander Afanasyevb6b21b32014-04-28 22:38:03 -070094 if (m_expr.size() < 2)
95 throw RegexMatcher::Error("Regexp compile error (cannot parse " + m_expr + ")");
96
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])
Alexander Afanasyevb6b21b32014-04-28 22:38:03 -0700104 throw RegexMatcher::Error("Regexp compile error (no matching ']' in " + m_expr + ")");
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -0700105
Alexander Afanasyevb6b21b32014-04-28 22:38:03 -0700106 if ('^' == m_expr[1]) {
107 m_isInclusion = false;
Alexander Afanasyev36b84cf2014-02-17 19:34:18 -0800108 compileMultipleComponents(2, lastIndex);
109 }
110 else
111 compileMultipleComponents(1, lastIndex);
112 break;
113 }
114 default:
Alexander Afanasyevb6b21b32014-04-28 22:38:03 -0700115 throw RegexMatcher::Error("Regexp compile error (cannot parse " + m_expr + ")");
Alexander Afanasyev36b84cf2014-02-17 19:34:18 -0800116 }
117}
118
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -0700119inline void
Alexander Afanasyev36b84cf2014-02-17 19:34:18 -0800120RegexComponentSetMatcher::compileSingleComponent()
121{
Alexander Afanasyev1dd95c52014-03-22 19:11:36 -0700122 size_t end = extractComponent(1);
Alexander Afanasyev36b84cf2014-02-17 19:34:18 -0800123
Alexander Afanasyev1dd95c52014-03-22 19:11:36 -0700124 if (m_expr.size() != end)
Alexander Afanasyev36b84cf2014-02-17 19:34:18 -0800125 {
Alexander Afanasyevb6b21b32014-04-28 22:38:03 -0700126 throw RegexMatcher::Error("Component expr error " + m_expr);
Alexander Afanasyev36b84cf2014-02-17 19:34:18 -0800127 }
128 else
129 {
130 shared_ptr<RegexComponentMatcher> component =
131 make_shared<RegexComponentMatcher>(m_expr.substr(1, end - 2), m_backrefManager);
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -0700132
133 m_components.insert(component);
Alexander Afanasyev36b84cf2014-02-17 19:34:18 -0800134 }
135}
136
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -0700137inline void
Alexander Afanasyevb6b21b32014-04-28 22:38:03 -0700138RegexComponentSetMatcher::compileMultipleComponents(size_t start, size_t lastIndex)
Alexander Afanasyev36b84cf2014-02-17 19:34:18 -0800139{
Alexander Afanasyevb6b21b32014-04-28 22:38:03 -0700140 size_t index = start;
141 size_t tempIndex = start;
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -0700142
Alexander Afanasyevb6b21b32014-04-28 22:38:03 -0700143 while (index < lastIndex) {
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -0700144 if ('<' != m_expr[index])
Alexander Afanasyevb6b21b32014-04-28 22:38:03 -0700145 throw RegexMatcher::Error("Component expr error " + m_expr);
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -0700146
Alexander Afanasyevb6b21b32014-04-28 22:38:03 -0700147 tempIndex = index + 1;
148 index = extractComponent(tempIndex);
Alexander Afanasyev36b84cf2014-02-17 19:34:18 -0800149
150 shared_ptr<RegexComponentMatcher> component =
Alexander Afanasyevb6b21b32014-04-28 22:38:03 -0700151 make_shared<RegexComponentMatcher>(m_expr.substr(tempIndex, index - tempIndex - 1),
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -0700152 m_backrefManager);
153
Alexander Afanasyev36b84cf2014-02-17 19:34:18 -0800154 m_components.insert(component);
155 }
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -0700156
157 if (index != lastIndex)
Alexander Afanasyevb6b21b32014-04-28 22:38:03 -0700158 throw RegexMatcher::Error("Not sufficient expr to parse " + m_expr);
Alexander Afanasyev36b84cf2014-02-17 19:34:18 -0800159}
160
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -0700161inline bool
Alexander Afanasyevb6b21b32014-04-28 22:38:03 -0700162RegexComponentSetMatcher::match(const Name& name, size_t offset, size_t len)
Alexander Afanasyev36b84cf2014-02-17 19:34:18 -0800163{
Alexander Afanasyevb6b21b32014-04-28 22:38:03 -0700164 bool isMatched = false;
Alexander Afanasyev36b84cf2014-02-17 19:34:18 -0800165
166 /* componentset only matches one component */
167 if (len != 1)
168 {
169 return false;
170 }
171
172 for (ComponentsSet::iterator it = m_components.begin();
173 it != m_components.end();
174 ++it)
175 {
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -0700176 if ((*it)->match(name, offset, len))
Alexander Afanasyev36b84cf2014-02-17 19:34:18 -0800177 {
Alexander Afanasyevb6b21b32014-04-28 22:38:03 -0700178 isMatched = true;
Alexander Afanasyev36b84cf2014-02-17 19:34:18 -0800179 break;
180 }
181 }
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -0700182
Alexander Afanasyev36b84cf2014-02-17 19:34:18 -0800183 m_matchResult.clear();
184
Alexander Afanasyevb6b21b32014-04-28 22:38:03 -0700185 if (m_isInclusion ? isMatched : !isMatched)
Alexander Afanasyev36b84cf2014-02-17 19:34:18 -0800186 {
187 m_matchResult.push_back(name.get(offset));
188 return true;
189 }
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -0700190 else
Alexander Afanasyev36b84cf2014-02-17 19:34:18 -0800191 return false;
192}
193
Alexander Afanasyevb6b21b32014-04-28 22:38:03 -0700194inline size_t
195RegexComponentSetMatcher::extractComponent(size_t index)
Alexander Afanasyev36b84cf2014-02-17 19:34:18 -0800196{
Alexander Afanasyevb6b21b32014-04-28 22:38:03 -0700197 size_t lcount = 1;
198 size_t rcount = 0;
Alexander Afanasyev36b84cf2014-02-17 19:34:18 -0800199
Alexander Afanasyevb6b21b32014-04-28 22:38:03 -0700200 while (lcount > rcount) {
201 switch (m_expr[index]) {
Alexander Afanasyev36b84cf2014-02-17 19:34:18 -0800202 case '<':
203 lcount++;
204 break;
205
206 case '>':
207 rcount++;
208 break;
209
210 case 0:
211 throw RegexMatcher::Error("Error: square brackets mismatch");
212 break;
213 }
214 index++;
215
216 }
217
218 return index;
219}
220
221} // namespace ndn
222
223#endif // NDN_UTIL_REGEX_COMPONENT_SET_MATCHER_HPP