blob: 5aed58fa5e8d8559730b26fd5bc34ae4ebd21720 [file] [log] [blame]
Yingdi Yu5e974202014-01-29 16:59:06 -08001/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil -*- */
2/**
3 * Copyright (C) 2013 Regents of the University of California.
4 * @author: Yingdi Yu <yingdi@cs.ucla.edu>
5 * See COPYING for copyright and distribution information.
6 */
7
Alexander Afanasyev36b84cf2014-02-17 19:34:18 -08008#ifndef NDN_UTIL_REGEX_COMPONENT_SET_MATCHER_HPP
9#define NDN_UTIL_REGEX_COMPONENT_SET_MATCHER_HPP
Yingdi Yu5e974202014-01-29 16:59:06 -080010
Alexander Afanasyev36b84cf2014-02-17 19:34:18 -080011#include "../../common.hpp"
Yingdi Yu5e974202014-01-29 16:59:06 -080012
13#include "regex-matcher.hpp"
14#include "regex-component-matcher.hpp"
15
Alexander Afanasyev36b84cf2014-02-17 19:34:18 -080016namespace ndn {
Yingdi Yu5e974202014-01-29 16:59:06 -080017
Alexander Afanasyev36b84cf2014-02-17 19:34:18 -080018class RegexComponentSetMatcher : public RegexMatcher {
Yingdi Yu5e974202014-01-29 16:59:06 -080019
20public:
21 /**
22 * @brief Create a RegexComponentSetMatcher matcher from expr
23 * @param expr The standard regular expression to match a component
24 * @param exact The flag to provide exact match
25 * @param backRefNum The starting back reference number
26 */
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -070027 RegexComponentSetMatcher(const std::string& expr, shared_ptr<RegexBackrefManager> backRefManager);
Yingdi Yu5e974202014-01-29 16:59:06 -080028
29 virtual ~RegexComponentSetMatcher();
30
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -070031 virtual bool
Alexander Afanasyev36b84cf2014-02-17 19:34:18 -080032 match(const Name& name, const int& offset, const int& len = 1);
Yingdi Yu5e974202014-01-29 16:59:06 -080033
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -070034protected:
Yingdi Yu5e974202014-01-29 16:59:06 -080035 /**
36 * @brief Compile the regular expression to generate the more matchers when necessary
37 * @returns true if compiling succeeds
38 */
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -070039 virtual void
Yingdi Yu5e974202014-01-29 16:59:06 -080040 compile();
41
42private:
43 int
44 extractComponent(int index);
45
46 void
47 compileSingleComponent();
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -070048
Yingdi Yu5e974202014-01-29 16:59:06 -080049 void
50 compileMultipleComponents(const int start, const int lastIndex);
51
52private:
Alexander Afanasyev36b84cf2014-02-17 19:34:18 -080053 typedef std::set<shared_ptr<RegexComponentMatcher> > ComponentsSet;
54 ComponentsSet m_components;
Yingdi Yu5e974202014-01-29 16:59:06 -080055 bool m_include;
56};
57
Yingdi Yu5e974202014-01-29 16:59:06 -080058
Alexander Afanasyev36b84cf2014-02-17 19:34:18 -080059inline
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -070060RegexComponentSetMatcher::RegexComponentSetMatcher(const std::string& expr,
61 shared_ptr<RegexBackrefManager> backRefManager)
Alexander Afanasyev36b84cf2014-02-17 19:34:18 -080062 : RegexMatcher(expr, EXPR_COMPONENT_SET, backRefManager),
63 m_include(true)
64{
65 // _LOG_TRACE ("Enter RegexComponentSetMatcher Constructor");
66 compile();
67 // _LOG_TRACE ("Exit RegexComponentSetMatcher Constructor");
68}
69
70inline
71RegexComponentSetMatcher::~RegexComponentSetMatcher()
72{
73 // ComponentsSet::iterator it = m_components.begin();
74
75 // for(; it != m_components.end(); it++)
76 // delete *it;
77}
78
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -070079inline void
Alexander Afanasyev36b84cf2014-02-17 19:34:18 -080080RegexComponentSetMatcher::compile()
81{
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -070082 switch (m_expr[0]){
Alexander Afanasyev36b84cf2014-02-17 19:34:18 -080083 case '<':
84 return compileSingleComponent();
85 case '[':
86 {
87 int lastIndex = m_expr.size() - 1;
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -070088 if (']' != m_expr[lastIndex])
Alexander Afanasyev36b84cf2014-02-17 19:34:18 -080089 throw RegexMatcher::Error(std::string("Error: RegexComponentSetMatcher.compile(): ")
90 + " No matched ']' " + m_expr);
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -070091
92 if ('^' == m_expr[1]){
Alexander Afanasyev36b84cf2014-02-17 19:34:18 -080093 m_include = false;
94 compileMultipleComponents(2, lastIndex);
95 }
96 else
97 compileMultipleComponents(1, lastIndex);
98 break;
99 }
100 default:
101 throw RegexMatcher::Error(std::string("Error: RegexComponentSetMatcher.compile(): ")
102 + "Parsing error in expr " + m_expr);
103 }
104}
105
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -0700106inline void
Alexander Afanasyev36b84cf2014-02-17 19:34:18 -0800107RegexComponentSetMatcher::compileSingleComponent()
108{
Alexander Afanasyev1dd95c52014-03-22 19:11:36 -0700109 size_t end = extractComponent(1);
Alexander Afanasyev36b84cf2014-02-17 19:34:18 -0800110
Alexander Afanasyev1dd95c52014-03-22 19:11:36 -0700111 if (m_expr.size() != end)
Alexander Afanasyev36b84cf2014-02-17 19:34:18 -0800112 {
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -0700113 throw RegexMatcher::Error(
114 std::string("Error: RegexComponentSetMatcher.compileSingleComponent: ") + m_expr);
Alexander Afanasyev36b84cf2014-02-17 19:34:18 -0800115 }
116 else
117 {
118 shared_ptr<RegexComponentMatcher> component =
119 make_shared<RegexComponentMatcher>(m_expr.substr(1, end - 2), m_backrefManager);
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -0700120
121 m_components.insert(component);
Alexander Afanasyev36b84cf2014-02-17 19:34:18 -0800122 }
123}
124
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -0700125inline void
Alexander Afanasyev36b84cf2014-02-17 19:34:18 -0800126RegexComponentSetMatcher::compileMultipleComponents(const int start, const int lastIndex)
127{
128 int index = start;
129 int tmp_index = start;
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -0700130
Alexander Afanasyev36b84cf2014-02-17 19:34:18 -0800131 while(index < lastIndex){
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -0700132 if ('<' != m_expr[index])
133 throw RegexMatcher::Error(
134 std::string("Error: RegexComponentSetMatcher.compileMultipleComponents: ") +
135 "Component expr error " + m_expr);
136
Alexander Afanasyev36b84cf2014-02-17 19:34:18 -0800137 tmp_index = index + 1;
138 index = extractComponent(tmp_index);
139
140 shared_ptr<RegexComponentMatcher> component =
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -0700141 make_shared<RegexComponentMatcher>(m_expr.substr(tmp_index, index - tmp_index - 1),
142 m_backrefManager);
143
Alexander Afanasyev36b84cf2014-02-17 19:34:18 -0800144 m_components.insert(component);
145 }
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -0700146
147 if (index != lastIndex)
148 throw RegexMatcher::Error(
149 std::string("Error: RegexComponentSetMatcher.compileMultipleComponents: ") +
150 "Not sufficient expr to parse " + m_expr);
Alexander Afanasyev36b84cf2014-02-17 19:34:18 -0800151}
152
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -0700153inline bool
154RegexComponentSetMatcher::match(const Name& name, const int& offset, const int& len)
Alexander Afanasyev36b84cf2014-02-17 19:34:18 -0800155{
156 bool matched = false;
157
158 /* componentset only matches one component */
159 if (len != 1)
160 {
161 return false;
162 }
163
164 for (ComponentsSet::iterator it = m_components.begin();
165 it != m_components.end();
166 ++it)
167 {
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -0700168 if ((*it)->match(name, offset, len))
Alexander Afanasyev36b84cf2014-02-17 19:34:18 -0800169 {
170 matched = true;
171 break;
172 }
173 }
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -0700174
Alexander Afanasyev36b84cf2014-02-17 19:34:18 -0800175 m_matchResult.clear();
176
177 if (m_include ? matched : !matched)
178 {
179 m_matchResult.push_back(name.get(offset));
180 return true;
181 }
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -0700182 else
Alexander Afanasyev36b84cf2014-02-17 19:34:18 -0800183 return false;
184}
185
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -0700186inline int
Alexander Afanasyev36b84cf2014-02-17 19:34:18 -0800187RegexComponentSetMatcher::extractComponent(int index)
188{
189 int lcount = 1;
190 int rcount = 0;
191
192 while(lcount > rcount){
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -0700193 switch (m_expr[index]){
Alexander Afanasyev36b84cf2014-02-17 19:34:18 -0800194 case '<':
195 lcount++;
196 break;
197
198 case '>':
199 rcount++;
200 break;
201
202 case 0:
203 throw RegexMatcher::Error("Error: square brackets mismatch");
204 break;
205 }
206 index++;
207
208 }
209
210 return index;
211}
212
213} // namespace ndn
214
215#endif // NDN_UTIL_REGEX_COMPONENT_SET_MATCHER_HPP