blob: 86af9064ed458c3fdbfd1f2a9e57f4a93c29b9c2 [file] [log] [blame]
Alexander Afanasyevc169a812014-05-20 20:37:29 -04001/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
Davide Pesavento45ab9a92017-11-05 19:34:31 -05002/*
3 * Copyright (c) 2013-2017 Regents of the University of California.
Alexander Afanasyevdfa52c42014-04-24 21:10:11 -07004 *
5 * This file is part of ndn-cxx library (NDN C++ library with eXperimental eXtensions).
Alexander Afanasyevdfa52c42014-04-24 21:10:11 -07006 *
Alexander Afanasyevc169a812014-05-20 20:37:29 -04007 * ndn-cxx library is free software: you can redistribute it and/or modify it under the
8 * terms of the GNU Lesser General Public License as published by the Free Software
9 * Foundation, either version 3 of the License, or (at your option) any later version.
10 *
11 * ndn-cxx library is distributed in the hope that it will be useful, but WITHOUT ANY
12 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
13 * PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
14 *
15 * You should have received copies of the GNU General Public License and GNU Lesser
16 * General Public License along with ndn-cxx, e.g., in COPYING.md file. If not, see
17 * <http://www.gnu.org/licenses/>.
18 *
19 * See AUTHORS.md for complete list of ndn-cxx authors and contributors.
Alexander Afanasyevdfa52c42014-04-24 21:10:11 -070020 *
21 * @author Yingdi Yu <http://irl.cs.ucla.edu/~yingdi/>
Yingdi Yu5e974202014-01-29 16:59:06 -080022 */
23
Alexander Afanasyev36b84cf2014-02-17 19:34:18 -080024#ifndef NDN_UTIL_REGEX_REGEX_REPEAT_MATCHER_HPP
25#define NDN_UTIL_REGEX_REGEX_REPEAT_MATCHER_HPP
26
Yingdi Yu5e974202014-01-29 16:59:06 -080027#include "regex-matcher.hpp"
28
Alexander Afanasyev36b84cf2014-02-17 19:34:18 -080029namespace ndn {
Yingdi Yu5e974202014-01-29 16:59:06 -080030
31class RegexRepeatMatcher : public RegexMatcher
32{
33public:
Alexander Afanasyevdfa52c42014-04-24 21:10:11 -070034 RegexRepeatMatcher(const std::string& expr,
Alexander Afanasyevb6b21b32014-04-28 22:38:03 -070035 shared_ptr<RegexBackrefManager> backrefManager,
36 size_t indicator);
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -070037
Davide Pesavento45ab9a92017-11-05 19:34:31 -050038 bool
39 match(const Name& name, size_t offset, size_t len) override;
Yingdi Yu5e974202014-01-29 16:59:06 -080040
41protected:
Davide Pesavento45ab9a92017-11-05 19:34:31 -050042 void
43 compile() override;
Yingdi Yu5e974202014-01-29 16:59:06 -080044
Yingdi Yu5e974202014-01-29 16:59:06 -080045private:
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -070046 bool
Yingdi Yu5e974202014-01-29 16:59:06 -080047 parseRepetition();
48
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -070049 bool
Davide Pesavento45ab9a92017-11-05 19:34:31 -050050 recursiveMatch(size_t repeat, const Name& name, size_t offset, size_t len);
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -070051
Yingdi Yu5e974202014-01-29 16:59:06 -080052private:
Alexander Afanasyevb6b21b32014-04-28 22:38:03 -070053 size_t m_indicator;
54 size_t m_repeatMin;
55 size_t m_repeatMax;
Yingdi Yu5e974202014-01-29 16:59:06 -080056};
57
Alexander Afanasyev36b84cf2014-02-17 19:34:18 -080058} // namespace ndn
Yingdi Yu5e974202014-01-29 16:59:06 -080059
Alexander Afanasyev36b84cf2014-02-17 19:34:18 -080060#include "regex-backref-matcher.hpp"
61#include "regex-component-set-matcher.hpp"
62
63namespace ndn {
64
65inline
Alexander Afanasyevdfa52c42014-04-24 21:10:11 -070066RegexRepeatMatcher::RegexRepeatMatcher(const std::string& expr,
67 shared_ptr<RegexBackrefManager> backrefManager,
Alexander Afanasyevb6b21b32014-04-28 22:38:03 -070068 size_t indicator)
Davide Pesavento45ab9a92017-11-05 19:34:31 -050069 : RegexMatcher(expr, EXPR_REPEAT_PATTERN, std::move(backrefManager))
Alexander Afanasyevdfa52c42014-04-24 21:10:11 -070070 , m_indicator(indicator)
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
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -070075inline void
Alexander Afanasyev36b84cf2014-02-17 19:34:18 -080076RegexRepeatMatcher::compile()
77{
Alexander Afanasyevb6b21b32014-04-28 22:38:03 -070078 if ('(' == m_expr[0]) {
Davide Pesavento45ab9a92017-11-05 19:34:31 -050079 auto matcher = make_shared<RegexBackrefMatcher>(m_expr.substr(0, m_indicator), m_backrefManager);
Alexander Afanasyev36b84cf2014-02-17 19:34:18 -080080 m_backrefManager->pushRef(matcher);
Davide Pesavento45ab9a92017-11-05 19:34:31 -050081 matcher->lateCompile();
82 m_matchers.push_back(std::move(matcher));
Alexander Afanasyev36b84cf2014-02-17 19:34:18 -080083 }
Davide Pesavento45ab9a92017-11-05 19:34:31 -050084 else {
85 m_matchers.push_back(make_shared<RegexComponentSetMatcher>(m_expr.substr(0, m_indicator),
86 m_backrefManager));
Alexander Afanasyev36b84cf2014-02-17 19:34:18 -080087 }
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -070088
Alexander Afanasyev36b84cf2014-02-17 19:34:18 -080089 parseRepetition();
Alexander Afanasyev36b84cf2014-02-17 19:34:18 -080090}
91
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -070092inline bool
Alexander Afanasyev36b84cf2014-02-17 19:34:18 -080093RegexRepeatMatcher::parseRepetition()
94{
Alexander Afanasyevb6b21b32014-04-28 22:38:03 -070095 size_t exprSize = m_expr.size();
96 const size_t MAX_REPETITIONS = std::numeric_limits<size_t>::max();
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -070097
Alexander Afanasyevb6b21b32014-04-28 22:38:03 -070098 if (exprSize == m_indicator) {
Alexander Afanasyev36b84cf2014-02-17 19:34:18 -080099 m_repeatMin = 1;
100 m_repeatMax = 1;
Alexander Afanasyev36b84cf2014-02-17 19:34:18 -0800101 return true;
102 }
Davide Pesavento45ab9a92017-11-05 19:34:31 -0500103
104 if (exprSize == (m_indicator + 1)) {
105 if ('?' == m_expr[m_indicator]) {
106 m_repeatMin = 0;
107 m_repeatMax = 1;
108 return true;
Alexander Afanasyev36b84cf2014-02-17 19:34:18 -0800109 }
Davide Pesavento45ab9a92017-11-05 19:34:31 -0500110 if ('+' == m_expr[m_indicator]) {
111 m_repeatMin = 1;
112 m_repeatMax = MAX_REPETITIONS;
113 return true;
114 }
115 if ('*' == m_expr[m_indicator]) {
116 m_repeatMin = 0;
117 m_repeatMax = MAX_REPETITIONS;
Alexander Afanasyev36b84cf2014-02-17 19:34:18 -0800118 return true;
119 }
120 }
Davide Pesavento45ab9a92017-11-05 19:34:31 -0500121 else {
122 std::string repeatStruct = m_expr.substr(m_indicator, exprSize - m_indicator);
123 size_t rsSize = repeatStruct.size();
124 size_t min = 0;
125 size_t max = 0;
126
127 if (boost::regex_match(repeatStruct, boost::regex("\\{[0-9]+,[0-9]+\\}"))) {
128 size_t separator = repeatStruct.find_first_of(',', 0);
129 min = std::atoi(repeatStruct.substr(1, separator - 1).data());
130 max = std::atoi(repeatStruct.substr(separator + 1, rsSize - separator - 2).data());
131 }
132 else if (boost::regex_match(repeatStruct, boost::regex("\\{,[0-9]+\\}"))) {
133 size_t separator = repeatStruct.find_first_of(',', 0);
134 min = 0;
135 max = std::atoi(repeatStruct.substr(separator + 1, rsSize - separator - 2).data());
136 }
137 else if (boost::regex_match(repeatStruct, boost::regex("\\{[0-9]+,\\}"))) {
138 size_t separator = repeatStruct.find_first_of(',', 0);
139 min = std::atoi(repeatStruct.substr(1, separator).data());
140 max = MAX_REPETITIONS;
141 }
142 else if (boost::regex_match(repeatStruct, boost::regex("\\{[0-9]+\\}"))) {
143 min = std::atoi(repeatStruct.substr(1, rsSize - 1).data());
144 max = min;
145 }
146 else
147 BOOST_THROW_EXCEPTION(Error(std::string("Error: RegexRepeatMatcher.ParseRepetition():")
148 + " Unrecognized format " + m_expr));
149
150 if (min > MAX_REPETITIONS || max > MAX_REPETITIONS || min > max)
151 BOOST_THROW_EXCEPTION(Error(std::string("Error: RegexRepeatMatcher.ParseRepetition():")
152 + " Wrong number " + m_expr));
153
154 m_repeatMin = min;
155 m_repeatMax = max;
156
157 return true;
158 }
159
Alexander Afanasyev36b84cf2014-02-17 19:34:18 -0800160 return false;
161}
162
163inline bool
Alexander Afanasyevb6b21b32014-04-28 22:38:03 -0700164RegexRepeatMatcher::match(const Name& name, size_t offset, size_t len)
Alexander Afanasyev36b84cf2014-02-17 19:34:18 -0800165{
Alexander Afanasyev36b84cf2014-02-17 19:34:18 -0800166 m_matchResult.clear();
167
Davide Pesavento45ab9a92017-11-05 19:34:31 -0500168 if (m_repeatMin == 0)
169 if (len == 0)
Alexander Afanasyev36b84cf2014-02-17 19:34:18 -0800170 return true;
171
Davide Pesavento45ab9a92017-11-05 19:34:31 -0500172 if (recursiveMatch(0, name, offset, len)) {
173 for (size_t i = offset; i < offset + len; i++)
174 m_matchResult.push_back(name.get(i));
175 return true;
176 }
177
178 return false;
Alexander Afanasyev36b84cf2014-02-17 19:34:18 -0800179}
180
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -0700181inline bool
Alexander Afanasyevb6b21b32014-04-28 22:38:03 -0700182RegexRepeatMatcher::recursiveMatch(size_t repeat, const Name& name, size_t offset, size_t len)
Alexander Afanasyev36b84cf2014-02-17 19:34:18 -0800183{
Alexander Afanasyevb6b21b32014-04-28 22:38:03 -0700184 ssize_t tried = len;
Alexander Afanasyev36b84cf2014-02-17 19:34:18 -0800185
Davide Pesavento45ab9a92017-11-05 19:34:31 -0500186 if (0 < len && repeat >= m_repeatMax) {
187 return false;
188 }
Alexander Afanasyev36b84cf2014-02-17 19:34:18 -0800189
Davide Pesavento45ab9a92017-11-05 19:34:31 -0500190 if (0 == len && repeat < m_repeatMin) {
191 return false;
192 }
Alexander Afanasyev36b84cf2014-02-17 19:34:18 -0800193
Davide Pesavento45ab9a92017-11-05 19:34:31 -0500194 if (0 == len && repeat >= m_repeatMin) {
195 return true;
196 }
197
198 auto matcher = m_matchers[0];
199 while (tried >= 0) {
200 if (matcher->match(name, offset, tried) &&
201 recursiveMatch(repeat + 1, name, offset + tried, len - tried))
Alexander Afanasyev36b84cf2014-02-17 19:34:18 -0800202 return true;
Davide Pesavento45ab9a92017-11-05 19:34:31 -0500203 tried--;
204 }
Alexander Afanasyev36b84cf2014-02-17 19:34:18 -0800205
206 return false;
207}
208
Alexander Afanasyev36b84cf2014-02-17 19:34:18 -0800209} // namespace ndn
210
211#endif // NDN_UTIL_REGEX_REGEX_REPEAT_MATCHER_HPP