blob: ffb4c6d0a1582f01396efc4c075cdaa1b9a2295e [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 Afanasyev36b84cf2014-02-17 19:34:18 -080027 RegexComponentSetMatcher(const std::string& expr, shared_ptr<RegexBackrefManager> backRefManager);
Yingdi Yu5e974202014-01-29 16:59:06 -080028
29 virtual ~RegexComponentSetMatcher();
30
31 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
34protected:
35 /**
36 * @brief Compile the regular expression to generate the more matchers when necessary
37 * @returns true if compiling succeeds
38 */
39 virtual void
40 compile();
41
42private:
43 int
44 extractComponent(int index);
45
46 void
47 compileSingleComponent();
48
49 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
60RegexComponentSetMatcher::RegexComponentSetMatcher(const std::string& expr, shared_ptr<RegexBackrefManager> backRefManager)
61 : RegexMatcher(expr, EXPR_COMPONENT_SET, backRefManager),
62 m_include(true)
63{
64 // _LOG_TRACE ("Enter RegexComponentSetMatcher Constructor");
65 compile();
66 // _LOG_TRACE ("Exit RegexComponentSetMatcher Constructor");
67}
68
69inline
70RegexComponentSetMatcher::~RegexComponentSetMatcher()
71{
72 // ComponentsSet::iterator it = m_components.begin();
73
74 // for(; it != m_components.end(); it++)
75 // delete *it;
76}
77
78inline void
79RegexComponentSetMatcher::compile()
80{
81 int index = 0;
82
83 switch(m_expr[0]){
84 case '<':
85 return compileSingleComponent();
86 case '[':
87 {
88 int lastIndex = m_expr.size() - 1;
89 if(']' != m_expr[lastIndex])
90 throw RegexMatcher::Error(std::string("Error: RegexComponentSetMatcher.compile(): ")
91 + " No matched ']' " + m_expr);
92
93 if('^' == m_expr[1]){
94 m_include = false;
95 compileMultipleComponents(2, lastIndex);
96 }
97 else
98 compileMultipleComponents(1, lastIndex);
99 break;
100 }
101 default:
102 throw RegexMatcher::Error(std::string("Error: RegexComponentSetMatcher.compile(): ")
103 + "Parsing error in expr " + m_expr);
104 }
105}
106
107inline void
108RegexComponentSetMatcher::compileSingleComponent()
109{
110 int end = extractComponent(1);
111
112 if(m_expr.size() != end)
113 {
114 throw RegexMatcher::Error(std::string("Error: RegexComponentSetMatcher.compileSingleComponent: ")
115 + m_expr);
116 }
117 else
118 {
119 shared_ptr<RegexComponentMatcher> component =
120 make_shared<RegexComponentMatcher>(m_expr.substr(1, end - 2), m_backrefManager);
121
122 m_components.insert(component);
123 }
124}
125
126inline void
127RegexComponentSetMatcher::compileMultipleComponents(const int start, const int lastIndex)
128{
129 int index = start;
130 int tmp_index = start;
131
132 while(index < lastIndex){
133 if('<' != m_expr[index])
134 throw RegexMatcher::Error(std::string("Error: RegexComponentSetMatcher.compileMultipleComponents: ")
135 + "Component expr error " + m_expr);
136
137 tmp_index = index + 1;
138 index = extractComponent(tmp_index);
139
140 shared_ptr<RegexComponentMatcher> component =
141 make_shared<RegexComponentMatcher>(m_expr.substr(tmp_index, index - tmp_index - 1), m_backrefManager);
142
143 m_components.insert(component);
144 }
145
146 if(index != lastIndex)
147 throw RegexMatcher::Error(std::string("Error: RegexComponentSetMatcher.compileMultipleComponents: ")
148 + "Not sufficient expr to parse " + m_expr);
149}
150
151inline bool
152RegexComponentSetMatcher::match(const Name & name, const int & offset, const int & len)
153{
154 bool matched = false;
155
156 /* componentset only matches one component */
157 if (len != 1)
158 {
159 return false;
160 }
161
162 for (ComponentsSet::iterator it = m_components.begin();
163 it != m_components.end();
164 ++it)
165 {
166 if((*it)->match(name, offset, len))
167 {
168 matched = true;
169 break;
170 }
171 }
172
173 m_matchResult.clear();
174
175 if (m_include ? matched : !matched)
176 {
177 m_matchResult.push_back(name.get(offset));
178 return true;
179 }
180 else
181 return false;
182}
183
184inline int
185RegexComponentSetMatcher::extractComponent(int index)
186{
187 int lcount = 1;
188 int rcount = 0;
189
190 while(lcount > rcount){
191 switch(m_expr[index]){
192 case '<':
193 lcount++;
194 break;
195
196 case '>':
197 rcount++;
198 break;
199
200 case 0:
201 throw RegexMatcher::Error("Error: square brackets mismatch");
202 break;
203 }
204 index++;
205
206 }
207
208 return index;
209}
210
211} // namespace ndn
212
213#endif // NDN_UTIL_REGEX_COMPONENT_SET_MATCHER_HPP