blob: bf49f134dc81fd8661b7e3b02a61337967230d38 [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_REGEX_REPEAT_MATCHER_HPP
16#define NDN_UTIL_REGEX_REGEX_REPEAT_MATCHER_HPP
17
18#include "../../common.hpp"
19
20#include <boost/regex.hpp>
Yingdi Yu5e974202014-01-29 16:59:06 -080021
22#include "regex-matcher.hpp"
23
Alexander Afanasyev36b84cf2014-02-17 19:34:18 -080024namespace ndn {
Yingdi Yu5e974202014-01-29 16:59:06 -080025
26class RegexRepeatMatcher : public RegexMatcher
27{
28public:
Alexander Afanasyevdfa52c42014-04-24 21:10:11 -070029 RegexRepeatMatcher(const std::string& expr,
Alexander Afanasyevb6b21b32014-04-28 22:38:03 -070030 shared_ptr<RegexBackrefManager> backrefManager,
31 size_t indicator);
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -070032
Alexander Afanasyevdfa52c42014-04-24 21:10:11 -070033 virtual
Alexander Afanasyevb6b21b32014-04-28 22:38:03 -070034 ~RegexRepeatMatcher()
35 {
36 }
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);
Yingdi Yu5e974202014-01-29 16:59:06 -080040
41protected:
42 /**
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
Yingdi Yu5e974202014-01-29 16:59:06 -080049private:
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -070050 bool
Yingdi Yu5e974202014-01-29 16:59:06 -080051 parseRepetition();
52
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -070053 bool
Alexander Afanasyevb6b21b32014-04-28 22:38:03 -070054 recursiveMatch(size_t repeat,
55 const Name& name,
56 size_t offset, size_t len);
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -070057
Yingdi Yu5e974202014-01-29 16:59:06 -080058private:
Alexander Afanasyevb6b21b32014-04-28 22:38:03 -070059 size_t m_indicator;
60 size_t m_repeatMin;
61 size_t m_repeatMax;
Yingdi Yu5e974202014-01-29 16:59:06 -080062};
63
Alexander Afanasyev36b84cf2014-02-17 19:34:18 -080064} // namespace ndn
Yingdi Yu5e974202014-01-29 16:59:06 -080065
Alexander Afanasyev36b84cf2014-02-17 19:34:18 -080066#include "regex-backref-matcher.hpp"
67#include "regex-component-set-matcher.hpp"
68
69namespace ndn {
70
71inline
Alexander Afanasyevdfa52c42014-04-24 21:10:11 -070072RegexRepeatMatcher::RegexRepeatMatcher(const std::string& expr,
73 shared_ptr<RegexBackrefManager> backrefManager,
Alexander Afanasyevb6b21b32014-04-28 22:38:03 -070074 size_t indicator)
75 : RegexMatcher(expr, EXPR_REPEAT_PATTERN, backrefManager)
Alexander Afanasyevdfa52c42014-04-24 21:10:11 -070076 , m_indicator(indicator)
Alexander Afanasyev36b84cf2014-02-17 19:34:18 -080077{
Alexander Afanasyev36b84cf2014-02-17 19:34:18 -080078 compile();
Alexander Afanasyev36b84cf2014-02-17 19:34:18 -080079}
80
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -070081inline void
Alexander Afanasyev36b84cf2014-02-17 19:34:18 -080082RegexRepeatMatcher::compile()
83{
Alexander Afanasyev36b84cf2014-02-17 19:34:18 -080084 shared_ptr<RegexMatcher> matcher;
85
Alexander Afanasyevb6b21b32014-04-28 22:38:03 -070086 if ('(' == m_expr[0]) {
Alexander Afanasyev36b84cf2014-02-17 19:34:18 -080087 matcher = make_shared<RegexBackrefMatcher>(m_expr.substr(0, m_indicator), m_backrefManager);
88 m_backrefManager->pushRef(matcher);
Alexander Afanasyevb67090a2014-04-29 22:31:01 -070089 dynamic_pointer_cast<RegexBackrefMatcher>(matcher)->lateCompile();
Alexander Afanasyev36b84cf2014-02-17 19:34:18 -080090 }
91 else{
Alexander Afanasyevdfa52c42014-04-24 21:10:11 -070092 matcher = make_shared<RegexComponentSetMatcher>(m_expr.substr(0, m_indicator),
93 m_backrefManager);
Alexander Afanasyev36b84cf2014-02-17 19:34:18 -080094 }
Alexander Afanasyevb6b21b32014-04-28 22:38:03 -070095 m_matchers.push_back(matcher);
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -070096
Alexander Afanasyev36b84cf2014-02-17 19:34:18 -080097 parseRepetition();
Alexander Afanasyev36b84cf2014-02-17 19:34:18 -080098}
99
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -0700100inline bool
Alexander Afanasyev36b84cf2014-02-17 19:34:18 -0800101RegexRepeatMatcher::parseRepetition()
102{
Alexander Afanasyevb6b21b32014-04-28 22:38:03 -0700103 size_t exprSize = m_expr.size();
104 const size_t MAX_REPETITIONS = std::numeric_limits<size_t>::max();
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -0700105
Alexander Afanasyevb6b21b32014-04-28 22:38:03 -0700106 if (exprSize == m_indicator) {
Alexander Afanasyev36b84cf2014-02-17 19:34:18 -0800107 m_repeatMin = 1;
108 m_repeatMax = 1;
109
110 return true;
111 }
Alexander Afanasyevb6b21b32014-04-28 22:38:03 -0700112 else {
113 if (exprSize == (m_indicator + 1)) {
114 if ('?' == m_expr[m_indicator]) {
Alexander Afanasyev36b84cf2014-02-17 19:34:18 -0800115 m_repeatMin = 0;
116 m_repeatMax = 1;
117 return true;
118 }
Alexander Afanasyevb6b21b32014-04-28 22:38:03 -0700119 if ('+' == m_expr[m_indicator]) {
Alexander Afanasyev36b84cf2014-02-17 19:34:18 -0800120 m_repeatMin = 1;
Alexander Afanasyevb6b21b32014-04-28 22:38:03 -0700121 m_repeatMax = MAX_REPETITIONS;
Alexander Afanasyev36b84cf2014-02-17 19:34:18 -0800122 return true;
123 }
Alexander Afanasyevb6b21b32014-04-28 22:38:03 -0700124 if ('*' == m_expr[m_indicator]) {
Alexander Afanasyev36b84cf2014-02-17 19:34:18 -0800125 m_repeatMin = 0;
Alexander Afanasyevb6b21b32014-04-28 22:38:03 -0700126 m_repeatMax = MAX_REPETITIONS;
Alexander Afanasyev36b84cf2014-02-17 19:34:18 -0800127 return true;
128 }
129 }
Alexander Afanasyevb6b21b32014-04-28 22:38:03 -0700130 else {
Alexander Afanasyev36b84cf2014-02-17 19:34:18 -0800131 std::string repeatStruct = m_expr.substr(m_indicator, exprSize - m_indicator);
Alexander Afanasyevb6b21b32014-04-28 22:38:03 -0700132 size_t rsSize = repeatStruct.size();
133 size_t min = 0;
134 size_t max = 0;
Alexander Afanasyev36b84cf2014-02-17 19:34:18 -0800135
Alexander Afanasyevb6b21b32014-04-28 22:38:03 -0700136 if (boost::regex_match(repeatStruct, boost::regex("\\{[0-9]+,[0-9]+\\}"))) {
137 size_t separator = repeatStruct.find_first_of(',', 0);
Alexander Afanasyev36b84cf2014-02-17 19:34:18 -0800138 min = atoi(repeatStruct.substr(1, separator - 1).c_str());
139 max = atoi(repeatStruct.substr(separator + 1, rsSize - separator - 2).c_str());
140 }
Alexander Afanasyevb6b21b32014-04-28 22:38:03 -0700141 else if (boost::regex_match(repeatStruct, boost::regex("\\{,[0-9]+\\}"))) {
142 size_t separator = repeatStruct.find_first_of(',', 0);
Alexander Afanasyev36b84cf2014-02-17 19:34:18 -0800143 min = 0;
144 max = atoi(repeatStruct.substr(separator + 1, rsSize - separator - 2).c_str());
145 }
Alexander Afanasyevb6b21b32014-04-28 22:38:03 -0700146 else if (boost::regex_match(repeatStruct, boost::regex("\\{[0-9]+,\\}"))) {
147 size_t separator = repeatStruct.find_first_of(',', 0);
Alexander Afanasyev36b84cf2014-02-17 19:34:18 -0800148 min = atoi(repeatStruct.substr(1, separator).c_str());
Alexander Afanasyevb6b21b32014-04-28 22:38:03 -0700149 max = MAX_REPETITIONS;
Alexander Afanasyev36b84cf2014-02-17 19:34:18 -0800150 }
Alexander Afanasyevb6b21b32014-04-28 22:38:03 -0700151 else if (boost::regex_match(repeatStruct, boost::regex("\\{[0-9]+\\}"))) {
Alexander Afanasyev36b84cf2014-02-17 19:34:18 -0800152 min = atoi(repeatStruct.substr(1, rsSize - 1).c_str());
153 max = min;
154 }
155 else
156 throw RegexMatcher::Error(std::string("Error: RegexRepeatMatcher.ParseRepetition(): ")
157 + "Unrecognized format "+ m_expr);
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -0700158
Alexander Afanasyevb6b21b32014-04-28 22:38:03 -0700159 if (min > MAX_REPETITIONS || max > MAX_REPETITIONS || min > max)
Alexander Afanasyev36b84cf2014-02-17 19:34:18 -0800160 throw RegexMatcher::Error(std::string("Error: RegexRepeatMatcher.ParseRepetition(): ")
161 + "Wrong number " + m_expr);
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -0700162
Alexander Afanasyev36b84cf2014-02-17 19:34:18 -0800163 m_repeatMin = min;
164 m_repeatMax = max;
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -0700165
Alexander Afanasyev36b84cf2014-02-17 19:34:18 -0800166 return true;
167 }
168 }
169 return false;
170}
171
172inline bool
Alexander Afanasyevb6b21b32014-04-28 22:38:03 -0700173RegexRepeatMatcher::match(const Name& name, size_t offset, size_t len)
Alexander Afanasyev36b84cf2014-02-17 19:34:18 -0800174{
Alexander Afanasyev36b84cf2014-02-17 19:34:18 -0800175 m_matchResult.clear();
176
177 if (0 == m_repeatMin)
178 if (0 == len)
179 return true;
180
181 if (recursiveMatch(0, name, offset, len))
182 {
Alexander Afanasyevb6b21b32014-04-28 22:38:03 -0700183 for (size_t i = offset; i < offset + len; i++)
Alexander Afanasyev36b84cf2014-02-17 19:34:18 -0800184 m_matchResult.push_back(name.get(i));
185 return true;
186 }
187 else
188 return false;
189}
190
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -0700191inline bool
Alexander Afanasyevb6b21b32014-04-28 22:38:03 -0700192RegexRepeatMatcher::recursiveMatch(size_t repeat, const Name& name, size_t offset, size_t len)
Alexander Afanasyev36b84cf2014-02-17 19:34:18 -0800193{
Alexander Afanasyevb6b21b32014-04-28 22:38:03 -0700194 ssize_t tried = len;
195 shared_ptr<RegexMatcher> matcher = m_matchers[0];
Alexander Afanasyev36b84cf2014-02-17 19:34:18 -0800196
197 if (0 < len && repeat >= m_repeatMax)
198 {
Alexander Afanasyev36b84cf2014-02-17 19:34:18 -0800199 return false;
200 }
201
202 if (0 == len && repeat < m_repeatMin)
203 {
Alexander Afanasyev36b84cf2014-02-17 19:34:18 -0800204 return false;
205 }
206
207 if (0 == len && repeat >= m_repeatMin)
208 {
Alexander Afanasyev36b84cf2014-02-17 19:34:18 -0800209 return true;
210 }
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -0700211
Alexander Afanasyevb6b21b32014-04-28 22:38:03 -0700212 while (tried >= 0)
Alexander Afanasyev36b84cf2014-02-17 19:34:18 -0800213 {
Alexander Afanasyevb6b21b32014-04-28 22:38:03 -0700214 if (matcher->match(name, offset, tried) &&
215 recursiveMatch(repeat + 1, name, offset + tried, len - tried))
Alexander Afanasyev36b84cf2014-02-17 19:34:18 -0800216 return true;
Alexander Afanasyevb6b21b32014-04-28 22:38:03 -0700217 tried--;
Alexander Afanasyev36b84cf2014-02-17 19:34:18 -0800218 }
219
220 return false;
221}
222
223
224} // namespace ndn
225
226#endif // NDN_UTIL_REGEX_REGEX_REPEAT_MATCHER_HPP