blob: e2ff78cbfd0f961115d0a2ac1a8600c298d92882 [file] [log] [blame]
Yingdi Yu5e974202014-01-29 16:59:06 -08001/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil -*- */
2/**
Alexander Afanasyevdfa52c42014-04-24 21:10:11 -07003 * Copyright (c) 2013-2014, Regents of the University of California.
4 * All rights reserved.
5 *
6 * This file is part of ndn-cxx library (NDN C++ library with eXperimental eXtensions).
7 * See AUTHORS.md for complete list of ndn-cxx authors and contributors.
8 *
9 * This file licensed under New BSD License. See COPYING for detailed information about
10 * ndn-cxx library copyright, permissions, and redistribution restrictions.
11 *
12 * @author Yingdi Yu <http://irl.cs.ucla.edu/~yingdi/>
Yingdi Yu5e974202014-01-29 16:59:06 -080013 */
14
Alexander Afanasyev36b84cf2014-02-17 19:34:18 -080015#ifndef NDN_UTIL_REGEX_COMPONENT_SET_MATCHER_HPP
16#define NDN_UTIL_REGEX_COMPONENT_SET_MATCHER_HPP
Yingdi Yu5e974202014-01-29 16:59:06 -080017
Alexander Afanasyev36b84cf2014-02-17 19:34:18 -080018#include "../../common.hpp"
Yingdi Yu5e974202014-01-29 16:59:06 -080019
20#include "regex-matcher.hpp"
21#include "regex-component-matcher.hpp"
22
Alexander Afanasyev36b84cf2014-02-17 19:34:18 -080023namespace ndn {
Yingdi Yu5e974202014-01-29 16:59:06 -080024
Alexander Afanasyev2a7f7202014-04-23 14:25:29 -070025class RegexComponentSetMatcher : public RegexMatcher
26{
Yingdi Yu5e974202014-01-29 16:59:06 -080027
28public:
29 /**
30 * @brief Create a RegexComponentSetMatcher matcher from expr
31 * @param expr The standard regular expression to match a component
32 * @param exact The flag to provide exact match
33 * @param backRefNum The starting back reference number
34 */
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -070035 RegexComponentSetMatcher(const std::string& expr, shared_ptr<RegexBackrefManager> backRefManager);
Yingdi Yu5e974202014-01-29 16:59:06 -080036
37 virtual ~RegexComponentSetMatcher();
38
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -070039 virtual bool
Alexander Afanasyev36b84cf2014-02-17 19:34:18 -080040 match(const Name& name, const int& offset, const int& len = 1);
Yingdi Yu5e974202014-01-29 16:59:06 -080041
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -070042protected:
Yingdi Yu5e974202014-01-29 16:59:06 -080043 /**
44 * @brief Compile the regular expression to generate the more matchers when necessary
45 * @returns true if compiling succeeds
46 */
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -070047 virtual void
Yingdi Yu5e974202014-01-29 16:59:06 -080048 compile();
49
50private:
51 int
52 extractComponent(int index);
53
54 void
55 compileSingleComponent();
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -070056
Yingdi Yu5e974202014-01-29 16:59:06 -080057 void
58 compileMultipleComponents(const int start, const int lastIndex);
59
60private:
Alexander Afanasyev36b84cf2014-02-17 19:34:18 -080061 typedef std::set<shared_ptr<RegexComponentMatcher> > ComponentsSet;
62 ComponentsSet m_components;
Yingdi Yu5e974202014-01-29 16:59:06 -080063 bool m_include;
64};
65
Yingdi Yu5e974202014-01-29 16:59:06 -080066
Alexander Afanasyev36b84cf2014-02-17 19:34:18 -080067inline
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -070068RegexComponentSetMatcher::RegexComponentSetMatcher(const std::string& expr,
69 shared_ptr<RegexBackrefManager> backRefManager)
Alexander Afanasyev36b84cf2014-02-17 19:34:18 -080070 : RegexMatcher(expr, EXPR_COMPONENT_SET, backRefManager),
71 m_include(true)
72{
73 // _LOG_TRACE ("Enter RegexComponentSetMatcher Constructor");
74 compile();
75 // _LOG_TRACE ("Exit RegexComponentSetMatcher Constructor");
76}
77
78inline
79RegexComponentSetMatcher::~RegexComponentSetMatcher()
80{
81 // ComponentsSet::iterator it = m_components.begin();
82
83 // for(; it != m_components.end(); it++)
84 // delete *it;
85}
86
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -070087inline void
Alexander Afanasyev36b84cf2014-02-17 19:34:18 -080088RegexComponentSetMatcher::compile()
89{
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -070090 switch (m_expr[0]){
Alexander Afanasyev36b84cf2014-02-17 19:34:18 -080091 case '<':
92 return compileSingleComponent();
93 case '[':
94 {
95 int lastIndex = m_expr.size() - 1;
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -070096 if (']' != m_expr[lastIndex])
Alexander Afanasyev36b84cf2014-02-17 19:34:18 -080097 throw RegexMatcher::Error(std::string("Error: RegexComponentSetMatcher.compile(): ")
98 + " No matched ']' " + m_expr);
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -070099
100 if ('^' == m_expr[1]){
Alexander Afanasyev36b84cf2014-02-17 19:34:18 -0800101 m_include = false;
102 compileMultipleComponents(2, lastIndex);
103 }
104 else
105 compileMultipleComponents(1, lastIndex);
106 break;
107 }
108 default:
109 throw RegexMatcher::Error(std::string("Error: RegexComponentSetMatcher.compile(): ")
110 + "Parsing error in expr " + m_expr);
111 }
112}
113
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -0700114inline void
Alexander Afanasyev36b84cf2014-02-17 19:34:18 -0800115RegexComponentSetMatcher::compileSingleComponent()
116{
Alexander Afanasyev1dd95c52014-03-22 19:11:36 -0700117 size_t end = extractComponent(1);
Alexander Afanasyev36b84cf2014-02-17 19:34:18 -0800118
Alexander Afanasyev1dd95c52014-03-22 19:11:36 -0700119 if (m_expr.size() != end)
Alexander Afanasyev36b84cf2014-02-17 19:34:18 -0800120 {
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -0700121 throw RegexMatcher::Error(
122 std::string("Error: RegexComponentSetMatcher.compileSingleComponent: ") + m_expr);
Alexander Afanasyev36b84cf2014-02-17 19:34:18 -0800123 }
124 else
125 {
126 shared_ptr<RegexComponentMatcher> component =
127 make_shared<RegexComponentMatcher>(m_expr.substr(1, end - 2), m_backrefManager);
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -0700128
129 m_components.insert(component);
Alexander Afanasyev36b84cf2014-02-17 19:34:18 -0800130 }
131}
132
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -0700133inline void
Alexander Afanasyev36b84cf2014-02-17 19:34:18 -0800134RegexComponentSetMatcher::compileMultipleComponents(const int start, const int lastIndex)
135{
136 int index = start;
137 int tmp_index = start;
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -0700138
Alexander Afanasyev36b84cf2014-02-17 19:34:18 -0800139 while(index < lastIndex){
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -0700140 if ('<' != m_expr[index])
141 throw RegexMatcher::Error(
142 std::string("Error: RegexComponentSetMatcher.compileMultipleComponents: ") +
143 "Component expr error " + m_expr);
144
Alexander Afanasyev36b84cf2014-02-17 19:34:18 -0800145 tmp_index = index + 1;
146 index = extractComponent(tmp_index);
147
148 shared_ptr<RegexComponentMatcher> component =
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -0700149 make_shared<RegexComponentMatcher>(m_expr.substr(tmp_index, index - tmp_index - 1),
150 m_backrefManager);
151
Alexander Afanasyev36b84cf2014-02-17 19:34:18 -0800152 m_components.insert(component);
153 }
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -0700154
155 if (index != lastIndex)
156 throw RegexMatcher::Error(
157 std::string("Error: RegexComponentSetMatcher.compileMultipleComponents: ") +
158 "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
162RegexComponentSetMatcher::match(const Name& name, const int& offset, const int& len)
Alexander Afanasyev36b84cf2014-02-17 19:34:18 -0800163{
164 bool matched = false;
165
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 {
178 matched = true;
179 break;
180 }
181 }
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -0700182
Alexander Afanasyev36b84cf2014-02-17 19:34:18 -0800183 m_matchResult.clear();
184
185 if (m_include ? matched : !matched)
186 {
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 Afanasyevfdbfc6d2014-04-14 15:12:11 -0700194inline int
Alexander Afanasyev36b84cf2014-02-17 19:34:18 -0800195RegexComponentSetMatcher::extractComponent(int index)
196{
197 int lcount = 1;
198 int rcount = 0;
199
200 while(lcount > rcount){
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -0700201 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