blob: 6bccffe2092c6e784a2c7250aefb3a2b9c417e5c [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 Afanasyev258ec2b2014-05-14 16:15:37 -070023#include <set>
24
Alexander Afanasyev36b84cf2014-02-17 19:34:18 -080025namespace ndn {
Yingdi Yu5e974202014-01-29 16:59:06 -080026
Alexander Afanasyev2a7f7202014-04-23 14:25:29 -070027class RegexComponentSetMatcher : public RegexMatcher
28{
Yingdi Yu5e974202014-01-29 16:59:06 -080029public:
30 /**
31 * @brief Create a RegexComponentSetMatcher matcher from expr
32 * @param expr The standard regular expression to match a component
Alexander Afanasyevb6b21b32014-04-28 22:38:03 -070033 * @param backrefManager Shared pointer to back-reference manager
Yingdi Yu5e974202014-01-29 16:59:06 -080034 */
Alexander Afanasyevb6b21b32014-04-28 22:38:03 -070035 RegexComponentSetMatcher(const std::string& expr, shared_ptr<RegexBackrefManager> backrefManager);
Yingdi Yu5e974202014-01-29 16:59:06 -080036
Alexander Afanasyevb6b21b32014-04-28 22:38:03 -070037 virtual
38 ~RegexComponentSetMatcher();
Yingdi Yu5e974202014-01-29 16:59:06 -080039
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -070040 virtual bool
Alexander Afanasyevb6b21b32014-04-28 22:38:03 -070041 match(const Name& name, size_t offset, size_t len = 1);
Yingdi Yu5e974202014-01-29 16:59:06 -080042
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -070043protected:
Yingdi Yu5e974202014-01-29 16:59:06 -080044 /**
45 * @brief Compile the regular expression to generate the more matchers when necessary
46 * @returns true if compiling succeeds
47 */
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -070048 virtual void
Yingdi Yu5e974202014-01-29 16:59:06 -080049 compile();
50
51private:
Alexander Afanasyevb6b21b32014-04-28 22:38:03 -070052 size_t
53 extractComponent(size_t index);
Yingdi Yu5e974202014-01-29 16:59:06 -080054
55 void
56 compileSingleComponent();
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -070057
Yingdi Yu5e974202014-01-29 16:59:06 -080058 void
Alexander Afanasyevb6b21b32014-04-28 22:38:03 -070059 compileMultipleComponents(size_t start, size_t lastIndex);
Yingdi Yu5e974202014-01-29 16:59:06 -080060
61private:
Alexander Afanasyev36b84cf2014-02-17 19:34:18 -080062 typedef std::set<shared_ptr<RegexComponentMatcher> > ComponentsSet;
63 ComponentsSet m_components;
Alexander Afanasyevb6b21b32014-04-28 22:38:03 -070064 bool m_isInclusion;
Yingdi Yu5e974202014-01-29 16:59:06 -080065};
66
Yingdi Yu5e974202014-01-29 16:59:06 -080067
Alexander Afanasyev36b84cf2014-02-17 19:34:18 -080068inline
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -070069RegexComponentSetMatcher::RegexComponentSetMatcher(const std::string& expr,
Alexander Afanasyevb6b21b32014-04-28 22:38:03 -070070 shared_ptr<RegexBackrefManager> backrefManager)
71 : RegexMatcher(expr, EXPR_COMPONENT_SET, backrefManager)
72 , m_isInclusion(true)
Alexander Afanasyev36b84cf2014-02-17 19:34:18 -080073{
Alexander Afanasyev36b84cf2014-02-17 19:34:18 -080074 compile();
Alexander Afanasyev36b84cf2014-02-17 19:34:18 -080075}
76
77inline
78RegexComponentSetMatcher::~RegexComponentSetMatcher()
79{
Alexander Afanasyev36b84cf2014-02-17 19:34:18 -080080}
81
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -070082inline void
Alexander Afanasyev36b84cf2014-02-17 19:34:18 -080083RegexComponentSetMatcher::compile()
84{
Alexander Afanasyevb6b21b32014-04-28 22:38:03 -070085 if (m_expr.size() < 2)
86 throw RegexMatcher::Error("Regexp compile error (cannot parse " + m_expr + ")");
87
88 switch (m_expr[0]) {
Alexander Afanasyev36b84cf2014-02-17 19:34:18 -080089 case '<':
90 return compileSingleComponent();
91 case '[':
92 {
Alexander Afanasyevb6b21b32014-04-28 22:38:03 -070093 size_t lastIndex = m_expr.size() - 1;
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -070094 if (']' != m_expr[lastIndex])
Alexander Afanasyevb6b21b32014-04-28 22:38:03 -070095 throw RegexMatcher::Error("Regexp compile error (no matching ']' in " + m_expr + ")");
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -070096
Alexander Afanasyevb6b21b32014-04-28 22:38:03 -070097 if ('^' == m_expr[1]) {
98 m_isInclusion = false;
Alexander Afanasyev36b84cf2014-02-17 19:34:18 -080099 compileMultipleComponents(2, lastIndex);
100 }
101 else
102 compileMultipleComponents(1, lastIndex);
103 break;
104 }
105 default:
Alexander Afanasyevb6b21b32014-04-28 22:38:03 -0700106 throw RegexMatcher::Error("Regexp compile error (cannot parse " + m_expr + ")");
Alexander Afanasyev36b84cf2014-02-17 19:34:18 -0800107 }
108}
109
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -0700110inline void
Alexander Afanasyev36b84cf2014-02-17 19:34:18 -0800111RegexComponentSetMatcher::compileSingleComponent()
112{
Alexander Afanasyev1dd95c52014-03-22 19:11:36 -0700113 size_t end = extractComponent(1);
Alexander Afanasyev36b84cf2014-02-17 19:34:18 -0800114
Alexander Afanasyev1dd95c52014-03-22 19:11:36 -0700115 if (m_expr.size() != end)
Alexander Afanasyev36b84cf2014-02-17 19:34:18 -0800116 {
Alexander Afanasyevb6b21b32014-04-28 22:38:03 -0700117 throw RegexMatcher::Error("Component expr error " + m_expr);
Alexander Afanasyev36b84cf2014-02-17 19:34:18 -0800118 }
119 else
120 {
121 shared_ptr<RegexComponentMatcher> component =
122 make_shared<RegexComponentMatcher>(m_expr.substr(1, end - 2), m_backrefManager);
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -0700123
124 m_components.insert(component);
Alexander Afanasyev36b84cf2014-02-17 19:34:18 -0800125 }
126}
127
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -0700128inline void
Alexander Afanasyevb6b21b32014-04-28 22:38:03 -0700129RegexComponentSetMatcher::compileMultipleComponents(size_t start, size_t lastIndex)
Alexander Afanasyev36b84cf2014-02-17 19:34:18 -0800130{
Alexander Afanasyevb6b21b32014-04-28 22:38:03 -0700131 size_t index = start;
132 size_t tempIndex = start;
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -0700133
Alexander Afanasyevb6b21b32014-04-28 22:38:03 -0700134 while (index < lastIndex) {
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -0700135 if ('<' != m_expr[index])
Alexander Afanasyevb6b21b32014-04-28 22:38:03 -0700136 throw RegexMatcher::Error("Component expr error " + m_expr);
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -0700137
Alexander Afanasyevb6b21b32014-04-28 22:38:03 -0700138 tempIndex = index + 1;
139 index = extractComponent(tempIndex);
Alexander Afanasyev36b84cf2014-02-17 19:34:18 -0800140
141 shared_ptr<RegexComponentMatcher> component =
Alexander Afanasyevb6b21b32014-04-28 22:38:03 -0700142 make_shared<RegexComponentMatcher>(m_expr.substr(tempIndex, index - tempIndex - 1),
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -0700143 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)
Alexander Afanasyevb6b21b32014-04-28 22:38:03 -0700149 throw RegexMatcher::Error("Not sufficient expr to parse " + m_expr);
Alexander Afanasyev36b84cf2014-02-17 19:34:18 -0800150}
151
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -0700152inline bool
Alexander Afanasyevb6b21b32014-04-28 22:38:03 -0700153RegexComponentSetMatcher::match(const Name& name, size_t offset, size_t len)
Alexander Afanasyev36b84cf2014-02-17 19:34:18 -0800154{
Alexander Afanasyevb6b21b32014-04-28 22:38:03 -0700155 bool isMatched = false;
Alexander Afanasyev36b84cf2014-02-17 19:34:18 -0800156
157 /* componentset only matches one component */
158 if (len != 1)
159 {
160 return false;
161 }
162
163 for (ComponentsSet::iterator it = m_components.begin();
164 it != m_components.end();
165 ++it)
166 {
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -0700167 if ((*it)->match(name, offset, len))
Alexander Afanasyev36b84cf2014-02-17 19:34:18 -0800168 {
Alexander Afanasyevb6b21b32014-04-28 22:38:03 -0700169 isMatched = true;
Alexander Afanasyev36b84cf2014-02-17 19:34:18 -0800170 break;
171 }
172 }
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -0700173
Alexander Afanasyev36b84cf2014-02-17 19:34:18 -0800174 m_matchResult.clear();
175
Alexander Afanasyevb6b21b32014-04-28 22:38:03 -0700176 if (m_isInclusion ? isMatched : !isMatched)
Alexander Afanasyev36b84cf2014-02-17 19:34:18 -0800177 {
178 m_matchResult.push_back(name.get(offset));
179 return true;
180 }
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -0700181 else
Alexander Afanasyev36b84cf2014-02-17 19:34:18 -0800182 return false;
183}
184
Alexander Afanasyevb6b21b32014-04-28 22:38:03 -0700185inline size_t
186RegexComponentSetMatcher::extractComponent(size_t index)
Alexander Afanasyev36b84cf2014-02-17 19:34:18 -0800187{
Alexander Afanasyevb6b21b32014-04-28 22:38:03 -0700188 size_t lcount = 1;
189 size_t rcount = 0;
Alexander Afanasyev36b84cf2014-02-17 19:34:18 -0800190
Alexander Afanasyevb6b21b32014-04-28 22:38:03 -0700191 while (lcount > rcount) {
192 switch (m_expr[index]) {
Alexander Afanasyev36b84cf2014-02-17 19:34:18 -0800193 case '<':
194 lcount++;
195 break;
196
197 case '>':
198 rcount++;
199 break;
200
201 case 0:
202 throw RegexMatcher::Error("Error: square brackets mismatch");
203 break;
204 }
205 index++;
206
207 }
208
209 return index;
210}
211
212} // namespace ndn
213
214#endif // NDN_UTIL_REGEX_COMPONENT_SET_MATCHER_HPP