blob: b8c9845dd4ca794153ae1e292b1a1821e011e73e [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 Afanasyev2a7f7202014-04-23 14:25:29 -070018class RegexComponentSetMatcher : public RegexMatcher
19{
Yingdi Yu5e974202014-01-29 16:59:06 -080020
21public:
22 /**
23 * @brief Create a RegexComponentSetMatcher matcher from expr
24 * @param expr The standard regular expression to match a component
25 * @param exact The flag to provide exact match
26 * @param backRefNum The starting back reference number
27 */
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -070028 RegexComponentSetMatcher(const std::string& expr, shared_ptr<RegexBackrefManager> backRefManager);
Yingdi Yu5e974202014-01-29 16:59:06 -080029
30 virtual ~RegexComponentSetMatcher();
31
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -070032 virtual bool
Alexander Afanasyev36b84cf2014-02-17 19:34:18 -080033 match(const Name& name, const int& offset, const int& len = 1);
Yingdi Yu5e974202014-01-29 16:59:06 -080034
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -070035protected:
Yingdi Yu5e974202014-01-29 16:59:06 -080036 /**
37 * @brief Compile the regular expression to generate the more matchers when necessary
38 * @returns true if compiling succeeds
39 */
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -070040 virtual void
Yingdi Yu5e974202014-01-29 16:59:06 -080041 compile();
42
43private:
44 int
45 extractComponent(int index);
46
47 void
48 compileSingleComponent();
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -070049
Yingdi Yu5e974202014-01-29 16:59:06 -080050 void
51 compileMultipleComponents(const int start, const int lastIndex);
52
53private:
Alexander Afanasyev36b84cf2014-02-17 19:34:18 -080054 typedef std::set<shared_ptr<RegexComponentMatcher> > ComponentsSet;
55 ComponentsSet m_components;
Yingdi Yu5e974202014-01-29 16:59:06 -080056 bool m_include;
57};
58
Yingdi Yu5e974202014-01-29 16:59:06 -080059
Alexander Afanasyev36b84cf2014-02-17 19:34:18 -080060inline
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -070061RegexComponentSetMatcher::RegexComponentSetMatcher(const std::string& expr,
62 shared_ptr<RegexBackrefManager> backRefManager)
Alexander Afanasyev36b84cf2014-02-17 19:34:18 -080063 : RegexMatcher(expr, EXPR_COMPONENT_SET, backRefManager),
64 m_include(true)
65{
66 // _LOG_TRACE ("Enter RegexComponentSetMatcher Constructor");
67 compile();
68 // _LOG_TRACE ("Exit RegexComponentSetMatcher Constructor");
69}
70
71inline
72RegexComponentSetMatcher::~RegexComponentSetMatcher()
73{
74 // ComponentsSet::iterator it = m_components.begin();
75
76 // for(; it != m_components.end(); it++)
77 // delete *it;
78}
79
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -070080inline void
Alexander Afanasyev36b84cf2014-02-17 19:34:18 -080081RegexComponentSetMatcher::compile()
82{
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -070083 switch (m_expr[0]){
Alexander Afanasyev36b84cf2014-02-17 19:34:18 -080084 case '<':
85 return compileSingleComponent();
86 case '[':
87 {
88 int lastIndex = m_expr.size() - 1;
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -070089 if (']' != m_expr[lastIndex])
Alexander Afanasyev36b84cf2014-02-17 19:34:18 -080090 throw RegexMatcher::Error(std::string("Error: RegexComponentSetMatcher.compile(): ")
91 + " No matched ']' " + m_expr);
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -070092
93 if ('^' == m_expr[1]){
Alexander Afanasyev36b84cf2014-02-17 19:34:18 -080094 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
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -0700107inline void
Alexander Afanasyev36b84cf2014-02-17 19:34:18 -0800108RegexComponentSetMatcher::compileSingleComponent()
109{
Alexander Afanasyev1dd95c52014-03-22 19:11:36 -0700110 size_t end = extractComponent(1);
Alexander Afanasyev36b84cf2014-02-17 19:34:18 -0800111
Alexander Afanasyev1dd95c52014-03-22 19:11:36 -0700112 if (m_expr.size() != end)
Alexander Afanasyev36b84cf2014-02-17 19:34:18 -0800113 {
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -0700114 throw RegexMatcher::Error(
115 std::string("Error: RegexComponentSetMatcher.compileSingleComponent: ") + m_expr);
Alexander Afanasyev36b84cf2014-02-17 19:34:18 -0800116 }
117 else
118 {
119 shared_ptr<RegexComponentMatcher> component =
120 make_shared<RegexComponentMatcher>(m_expr.substr(1, end - 2), m_backrefManager);
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -0700121
122 m_components.insert(component);
Alexander Afanasyev36b84cf2014-02-17 19:34:18 -0800123 }
124}
125
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -0700126inline void
Alexander Afanasyev36b84cf2014-02-17 19:34:18 -0800127RegexComponentSetMatcher::compileMultipleComponents(const int start, const int lastIndex)
128{
129 int index = start;
130 int tmp_index = start;
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -0700131
Alexander Afanasyev36b84cf2014-02-17 19:34:18 -0800132 while(index < lastIndex){
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -0700133 if ('<' != m_expr[index])
134 throw RegexMatcher::Error(
135 std::string("Error: RegexComponentSetMatcher.compileMultipleComponents: ") +
136 "Component expr error " + m_expr);
137
Alexander Afanasyev36b84cf2014-02-17 19:34:18 -0800138 tmp_index = index + 1;
139 index = extractComponent(tmp_index);
140
141 shared_ptr<RegexComponentMatcher> component =
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -0700142 make_shared<RegexComponentMatcher>(m_expr.substr(tmp_index, index - tmp_index - 1),
143 m_backrefManager);
144
Alexander Afanasyev36b84cf2014-02-17 19:34:18 -0800145 m_components.insert(component);
146 }
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -0700147
148 if (index != lastIndex)
149 throw RegexMatcher::Error(
150 std::string("Error: RegexComponentSetMatcher.compileMultipleComponents: ") +
151 "Not sufficient expr to parse " + m_expr);
Alexander Afanasyev36b84cf2014-02-17 19:34:18 -0800152}
153
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -0700154inline bool
155RegexComponentSetMatcher::match(const Name& name, const int& offset, const int& len)
Alexander Afanasyev36b84cf2014-02-17 19:34:18 -0800156{
157 bool matched = false;
158
159 /* componentset only matches one component */
160 if (len != 1)
161 {
162 return false;
163 }
164
165 for (ComponentsSet::iterator it = m_components.begin();
166 it != m_components.end();
167 ++it)
168 {
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -0700169 if ((*it)->match(name, offset, len))
Alexander Afanasyev36b84cf2014-02-17 19:34:18 -0800170 {
171 matched = true;
172 break;
173 }
174 }
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -0700175
Alexander Afanasyev36b84cf2014-02-17 19:34:18 -0800176 m_matchResult.clear();
177
178 if (m_include ? matched : !matched)
179 {
180 m_matchResult.push_back(name.get(offset));
181 return true;
182 }
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -0700183 else
Alexander Afanasyev36b84cf2014-02-17 19:34:18 -0800184 return false;
185}
186
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -0700187inline int
Alexander Afanasyev36b84cf2014-02-17 19:34:18 -0800188RegexComponentSetMatcher::extractComponent(int index)
189{
190 int lcount = 1;
191 int rcount = 0;
192
193 while(lcount > rcount){
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -0700194 switch (m_expr[index]){
Alexander Afanasyev36b84cf2014-02-17 19:34:18 -0800195 case '<':
196 lcount++;
197 break;
198
199 case '>':
200 rcount++;
201 break;
202
203 case 0:
204 throw RegexMatcher::Error("Error: square brackets mismatch");
205 break;
206 }
207 index++;
208
209 }
210
211 return index;
212}
213
214} // namespace ndn
215
216#endif // NDN_UTIL_REGEX_COMPONENT_SET_MATCHER_HPP