blob: 8e0e908a997bfb335c7106af962e62df81b937b0 [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 -080027public:
28 /**
29 * @brief Create a RegexComponentSetMatcher matcher from expr
30 * @param expr The standard regular expression to match a component
Alexander Afanasyevb6b21b32014-04-28 22:38:03 -070031 * @param backrefManager Shared pointer to back-reference manager
Yingdi Yu5e974202014-01-29 16:59:06 -080032 */
Alexander Afanasyevb6b21b32014-04-28 22:38:03 -070033 RegexComponentSetMatcher(const std::string& expr, shared_ptr<RegexBackrefManager> backrefManager);
Yingdi Yu5e974202014-01-29 16:59:06 -080034
Alexander Afanasyevb6b21b32014-04-28 22:38:03 -070035 virtual
36 ~RegexComponentSetMatcher();
Yingdi Yu5e974202014-01-29 16:59:06 -080037
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -070038 virtual bool
Alexander Afanasyevb6b21b32014-04-28 22:38:03 -070039 match(const Name& name, size_t offset, size_t len = 1);
Yingdi Yu5e974202014-01-29 16:59:06 -080040
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -070041protected:
Yingdi Yu5e974202014-01-29 16:59:06 -080042 /**
43 * @brief Compile the regular expression to generate the more matchers when necessary
44 * @returns true if compiling succeeds
45 */
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -070046 virtual void
Yingdi Yu5e974202014-01-29 16:59:06 -080047 compile();
48
49private:
Alexander Afanasyevb6b21b32014-04-28 22:38:03 -070050 size_t
51 extractComponent(size_t index);
Yingdi Yu5e974202014-01-29 16:59:06 -080052
53 void
54 compileSingleComponent();
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -070055
Yingdi Yu5e974202014-01-29 16:59:06 -080056 void
Alexander Afanasyevb6b21b32014-04-28 22:38:03 -070057 compileMultipleComponents(size_t start, size_t lastIndex);
Yingdi Yu5e974202014-01-29 16:59:06 -080058
59private:
Alexander Afanasyev36b84cf2014-02-17 19:34:18 -080060 typedef std::set<shared_ptr<RegexComponentMatcher> > ComponentsSet;
61 ComponentsSet m_components;
Alexander Afanasyevb6b21b32014-04-28 22:38:03 -070062 bool m_isInclusion;
Yingdi Yu5e974202014-01-29 16:59:06 -080063};
64
Yingdi Yu5e974202014-01-29 16:59:06 -080065
Alexander Afanasyev36b84cf2014-02-17 19:34:18 -080066inline
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -070067RegexComponentSetMatcher::RegexComponentSetMatcher(const std::string& expr,
Alexander Afanasyevb6b21b32014-04-28 22:38:03 -070068 shared_ptr<RegexBackrefManager> backrefManager)
69 : RegexMatcher(expr, EXPR_COMPONENT_SET, backrefManager)
70 , m_isInclusion(true)
Alexander Afanasyev36b84cf2014-02-17 19:34:18 -080071{
Alexander Afanasyev36b84cf2014-02-17 19:34:18 -080072 compile();
Alexander Afanasyev36b84cf2014-02-17 19:34:18 -080073}
74
75inline
76RegexComponentSetMatcher::~RegexComponentSetMatcher()
77{
Alexander Afanasyev36b84cf2014-02-17 19:34:18 -080078}
79
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -070080inline void
Alexander Afanasyev36b84cf2014-02-17 19:34:18 -080081RegexComponentSetMatcher::compile()
82{
Alexander Afanasyevb6b21b32014-04-28 22:38:03 -070083 if (m_expr.size() < 2)
84 throw RegexMatcher::Error("Regexp compile error (cannot parse " + m_expr + ")");
85
86 switch (m_expr[0]) {
Alexander Afanasyev36b84cf2014-02-17 19:34:18 -080087 case '<':
88 return compileSingleComponent();
89 case '[':
90 {
Alexander Afanasyevb6b21b32014-04-28 22:38:03 -070091 size_t lastIndex = m_expr.size() - 1;
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -070092 if (']' != m_expr[lastIndex])
Alexander Afanasyevb6b21b32014-04-28 22:38:03 -070093 throw RegexMatcher::Error("Regexp compile error (no matching ']' in " + m_expr + ")");
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -070094
Alexander Afanasyevb6b21b32014-04-28 22:38:03 -070095 if ('^' == m_expr[1]) {
96 m_isInclusion = false;
Alexander Afanasyev36b84cf2014-02-17 19:34:18 -080097 compileMultipleComponents(2, lastIndex);
98 }
99 else
100 compileMultipleComponents(1, lastIndex);
101 break;
102 }
103 default:
Alexander Afanasyevb6b21b32014-04-28 22:38:03 -0700104 throw RegexMatcher::Error("Regexp compile error (cannot parse " + m_expr + ")");
Alexander Afanasyev36b84cf2014-02-17 19:34:18 -0800105 }
106}
107
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -0700108inline void
Alexander Afanasyev36b84cf2014-02-17 19:34:18 -0800109RegexComponentSetMatcher::compileSingleComponent()
110{
Alexander Afanasyev1dd95c52014-03-22 19:11:36 -0700111 size_t end = extractComponent(1);
Alexander Afanasyev36b84cf2014-02-17 19:34:18 -0800112
Alexander Afanasyev1dd95c52014-03-22 19:11:36 -0700113 if (m_expr.size() != end)
Alexander Afanasyev36b84cf2014-02-17 19:34:18 -0800114 {
Alexander Afanasyevb6b21b32014-04-28 22:38:03 -0700115 throw RegexMatcher::Error("Component expr error " + 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 Afanasyevb6b21b32014-04-28 22:38:03 -0700127RegexComponentSetMatcher::compileMultipleComponents(size_t start, size_t lastIndex)
Alexander Afanasyev36b84cf2014-02-17 19:34:18 -0800128{
Alexander Afanasyevb6b21b32014-04-28 22:38:03 -0700129 size_t index = start;
130 size_t tempIndex = start;
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -0700131
Alexander Afanasyevb6b21b32014-04-28 22:38:03 -0700132 while (index < lastIndex) {
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -0700133 if ('<' != m_expr[index])
Alexander Afanasyevb6b21b32014-04-28 22:38:03 -0700134 throw RegexMatcher::Error("Component expr error " + m_expr);
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -0700135
Alexander Afanasyevb6b21b32014-04-28 22:38:03 -0700136 tempIndex = index + 1;
137 index = extractComponent(tempIndex);
Alexander Afanasyev36b84cf2014-02-17 19:34:18 -0800138
139 shared_ptr<RegexComponentMatcher> component =
Alexander Afanasyevb6b21b32014-04-28 22:38:03 -0700140 make_shared<RegexComponentMatcher>(m_expr.substr(tempIndex, index - tempIndex - 1),
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -0700141 m_backrefManager);
142
Alexander Afanasyev36b84cf2014-02-17 19:34:18 -0800143 m_components.insert(component);
144 }
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -0700145
146 if (index != lastIndex)
Alexander Afanasyevb6b21b32014-04-28 22:38:03 -0700147 throw RegexMatcher::Error("Not sufficient expr to parse " + m_expr);
Alexander Afanasyev36b84cf2014-02-17 19:34:18 -0800148}
149
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -0700150inline bool
Alexander Afanasyevb6b21b32014-04-28 22:38:03 -0700151RegexComponentSetMatcher::match(const Name& name, size_t offset, size_t len)
Alexander Afanasyev36b84cf2014-02-17 19:34:18 -0800152{
Alexander Afanasyevb6b21b32014-04-28 22:38:03 -0700153 bool isMatched = false;
Alexander Afanasyev36b84cf2014-02-17 19:34:18 -0800154
155 /* componentset only matches one component */
156 if (len != 1)
157 {
158 return false;
159 }
160
161 for (ComponentsSet::iterator it = m_components.begin();
162 it != m_components.end();
163 ++it)
164 {
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -0700165 if ((*it)->match(name, offset, len))
Alexander Afanasyev36b84cf2014-02-17 19:34:18 -0800166 {
Alexander Afanasyevb6b21b32014-04-28 22:38:03 -0700167 isMatched = true;
Alexander Afanasyev36b84cf2014-02-17 19:34:18 -0800168 break;
169 }
170 }
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -0700171
Alexander Afanasyev36b84cf2014-02-17 19:34:18 -0800172 m_matchResult.clear();
173
Alexander Afanasyevb6b21b32014-04-28 22:38:03 -0700174 if (m_isInclusion ? isMatched : !isMatched)
Alexander Afanasyev36b84cf2014-02-17 19:34:18 -0800175 {
176 m_matchResult.push_back(name.get(offset));
177 return true;
178 }
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -0700179 else
Alexander Afanasyev36b84cf2014-02-17 19:34:18 -0800180 return false;
181}
182
Alexander Afanasyevb6b21b32014-04-28 22:38:03 -0700183inline size_t
184RegexComponentSetMatcher::extractComponent(size_t index)
Alexander Afanasyev36b84cf2014-02-17 19:34:18 -0800185{
Alexander Afanasyevb6b21b32014-04-28 22:38:03 -0700186 size_t lcount = 1;
187 size_t rcount = 0;
Alexander Afanasyev36b84cf2014-02-17 19:34:18 -0800188
Alexander Afanasyevb6b21b32014-04-28 22:38:03 -0700189 while (lcount > rcount) {
190 switch (m_expr[index]) {
Alexander Afanasyev36b84cf2014-02-17 19:34:18 -0800191 case '<':
192 lcount++;
193 break;
194
195 case '>':
196 rcount++;
197 break;
198
199 case 0:
200 throw RegexMatcher::Error("Error: square brackets mismatch");
201 break;
202 }
203 index++;
204
205 }
206
207 return index;
208}
209
210} // namespace ndn
211
212#endif // NDN_UTIL_REGEX_COMPONENT_SET_MATCHER_HPP