blob: 7bf036674d281f4efcd1104bcfabd7e2403b38f9 [file] [log] [blame]
Alexander Afanasyevc169a812014-05-20 20:37:29 -04001/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
Davide Pesavento88a0d812017-08-19 21:31:42 -04002/*
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_PATTERN_LIST_MATCHER_HPP
25#define NDN_UTIL_REGEX_REGEX_PATTERN_LIST_MATCHER_HPP
Yingdi Yu5e974202014-01-29 16:59:06 -080026
Yingdi Yu5e974202014-01-29 16:59:06 -080027#include "regex-matcher.hpp"
28
Alexander Afanasyev36b84cf2014-02-17 19:34:18 -080029namespace ndn {
30
Yingdi Yu5e974202014-01-29 16:59:06 -080031class RegexPatternListMatcher : public RegexMatcher
32{
33public:
Alexander Afanasyevb6b21b32014-04-28 22:38:03 -070034 RegexPatternListMatcher(const std::string& expr, shared_ptr<RegexBackrefManager> backrefManager);
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -070035
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -070036protected:
Davide Pesavento88a0d812017-08-19 21:31:42 -040037 void
38 compile() override;
Yingdi Yu5e974202014-01-29 16:59:06 -080039
40private:
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -070041 bool
Alexander Afanasyevb6b21b32014-04-28 22:38:03 -070042 extractPattern(size_t index, size_t* next);
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -070043
Davide Pesavento45ab9a92017-11-05 19:34:31 -050044 size_t
Alexander Afanasyev1dd95c52014-03-22 19:11:36 -070045 extractSubPattern(const char left, const char right, size_t index);
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -070046
Davide Pesavento45ab9a92017-11-05 19:34:31 -050047 size_t
Alexander Afanasyev1dd95c52014-03-22 19:11:36 -070048 extractRepetition(size_t index);
Yingdi Yu5e974202014-01-29 16:59:06 -080049};
Yingdi Yu5e974202014-01-29 16:59:06 -080050
Alexander Afanasyev36b84cf2014-02-17 19:34:18 -080051} // namespace ndn
52
Alexander Afanasyev36b84cf2014-02-17 19:34:18 -080053#include "regex-backref-matcher.hpp"
Davide Pesavento45ab9a92017-11-05 19:34:31 -050054#include "regex-repeat-matcher.hpp"
Alexander Afanasyev36b84cf2014-02-17 19:34:18 -080055
56namespace ndn {
57
Alexander Afanasyevdfa52c42014-04-24 21:10:11 -070058inline
59RegexPatternListMatcher::RegexPatternListMatcher(const std::string& expr,
60 shared_ptr<RegexBackrefManager> backrefManager)
Davide Pesavento45ab9a92017-11-05 19:34:31 -050061 : RegexMatcher(expr, EXPR_PATTERN_LIST, std::move(backrefManager))
Alexander Afanasyev36b84cf2014-02-17 19:34:18 -080062{
63 compile();
64}
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -070065
66inline void
Alexander Afanasyev36b84cf2014-02-17 19:34:18 -080067RegexPatternListMatcher::compile()
68{
Alexander Afanasyevb6b21b32014-04-28 22:38:03 -070069 size_t len = m_expr.size();
70 size_t index = 0;
71 size_t subHead = index;
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -070072
Alexander Afanasyevb6b21b32014-04-28 22:38:03 -070073 while (index < len) {
Alexander Afanasyev36b84cf2014-02-17 19:34:18 -080074 subHead = index;
75
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -070076 if (!extractPattern(subHead, &index))
Davide Pesavento45ab9a92017-11-05 19:34:31 -050077 BOOST_THROW_EXCEPTION(Error("Compile error"));
Alexander Afanasyev36b84cf2014-02-17 19:34:18 -080078 }
79}
80
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -070081inline bool
Alexander Afanasyevb6b21b32014-04-28 22:38:03 -070082RegexPatternListMatcher::extractPattern(size_t index, size_t* next)
Alexander Afanasyev36b84cf2014-02-17 19:34:18 -080083{
Alexander Afanasyevb6b21b32014-04-28 22:38:03 -070084 size_t start = index;
85 size_t end = index;
86 size_t indicator = index;
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -070087
Alexander Afanasyevb6b21b32014-04-28 22:38:03 -070088 switch (m_expr[index]) {
Alexander Afanasyev36b84cf2014-02-17 19:34:18 -080089 case '(':
90 index++;
91 index = extractSubPattern('(', ')', index);
92 indicator = index;
93 end = extractRepetition(index);
Alexander Afanasyevb6b21b32014-04-28 22:38:03 -070094 if (indicator == end) {
Davide Pesavento45ab9a92017-11-05 19:34:31 -050095 auto matcher = make_shared<RegexBackrefMatcher>(m_expr.substr(start, end - start),
96 m_backrefManager);
Alexander Afanasyev36b84cf2014-02-17 19:34:18 -080097 m_backrefManager->pushRef(matcher);
Davide Pesavento45ab9a92017-11-05 19:34:31 -050098 matcher->lateCompile();
99 m_matchers.push_back(std::move(matcher));
Alexander Afanasyev36b84cf2014-02-17 19:34:18 -0800100 }
101 else
Alexander Afanasyevb6b21b32014-04-28 22:38:03 -0700102 m_matchers.push_back(make_shared<RegexRepeatMatcher>(m_expr.substr(start, end - start),
103 m_backrefManager, indicator - start));
Alexander Afanasyev36b84cf2014-02-17 19:34:18 -0800104 break;
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -0700105
Alexander Afanasyev36b84cf2014-02-17 19:34:18 -0800106 case '<':
107 index++;
Alexander Afanasyevb6b21b32014-04-28 22:38:03 -0700108 index = extractSubPattern('<', '>', index);
Alexander Afanasyev36b84cf2014-02-17 19:34:18 -0800109 indicator = index;
110 end = extractRepetition(index);
Alexander Afanasyevb6b21b32014-04-28 22:38:03 -0700111 m_matchers.push_back(make_shared<RegexRepeatMatcher>(m_expr.substr(start, end - start),
112 m_backrefManager, indicator - start));
Alexander Afanasyev36b84cf2014-02-17 19:34:18 -0800113 break;
114
115 case '[':
116 index++;
Alexander Afanasyevb6b21b32014-04-28 22:38:03 -0700117 index = extractSubPattern('[', ']', index);
Alexander Afanasyev36b84cf2014-02-17 19:34:18 -0800118 indicator = index;
119 end = extractRepetition(index);
Alexander Afanasyevb6b21b32014-04-28 22:38:03 -0700120 m_matchers.push_back(make_shared<RegexRepeatMatcher>(m_expr.substr(start, end - start),
121 m_backrefManager, indicator - start));
Alexander Afanasyev36b84cf2014-02-17 19:34:18 -0800122 break;
123
124 default:
Davide Pesavento45ab9a92017-11-05 19:34:31 -0500125 BOOST_THROW_EXCEPTION(Error("Unexpected syntax"));
Alexander Afanasyev36b84cf2014-02-17 19:34:18 -0800126 }
127
128 *next = end;
Alexander Afanasyev36b84cf2014-02-17 19:34:18 -0800129 return true;
130}
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -0700131
Davide Pesavento45ab9a92017-11-05 19:34:31 -0500132inline size_t
Alexander Afanasyev1dd95c52014-03-22 19:11:36 -0700133RegexPatternListMatcher::extractSubPattern(const char left, const char right, size_t index)
Alexander Afanasyev36b84cf2014-02-17 19:34:18 -0800134{
Alexander Afanasyev1dd95c52014-03-22 19:11:36 -0700135 size_t lcount = 1;
136 size_t rcount = 0;
Alexander Afanasyev36b84cf2014-02-17 19:34:18 -0800137
Alexander Afanasyevb6b21b32014-04-28 22:38:03 -0700138 while (lcount > rcount) {
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -0700139 if (index >= m_expr.size())
Davide Pesavento45ab9a92017-11-05 19:34:31 -0500140 BOOST_THROW_EXCEPTION(Error("Parenthesis mismatch"));
Alexander Afanasyev36b84cf2014-02-17 19:34:18 -0800141
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -0700142 if (left == m_expr[index])
Alexander Afanasyev36b84cf2014-02-17 19:34:18 -0800143 lcount++;
144
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -0700145 if (right == m_expr[index])
Alexander Afanasyev36b84cf2014-02-17 19:34:18 -0800146 rcount++;
147
148 index++;
149 }
Davide Pesavento45ab9a92017-11-05 19:34:31 -0500150
Alexander Afanasyev36b84cf2014-02-17 19:34:18 -0800151 return index;
152}
153
Davide Pesavento45ab9a92017-11-05 19:34:31 -0500154inline size_t
Alexander Afanasyev1dd95c52014-03-22 19:11:36 -0700155RegexPatternListMatcher::extractRepetition(size_t index)
Alexander Afanasyev36b84cf2014-02-17 19:34:18 -0800156{
Alexander Afanasyev1dd95c52014-03-22 19:11:36 -0700157 size_t exprSize = m_expr.size();
Alexander Afanasyev36b84cf2014-02-17 19:34:18 -0800158
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -0700159 if (index == exprSize)
Alexander Afanasyev36b84cf2014-02-17 19:34:18 -0800160 return index;
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -0700161
Alexander Afanasyevb6b21b32014-04-28 22:38:03 -0700162 if (('+' == m_expr[index] || '?' == m_expr[index] || '*' == m_expr[index])) {
Alexander Afanasyev36b84cf2014-02-17 19:34:18 -0800163 return ++index;
164 }
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -0700165
Alexander Afanasyevb6b21b32014-04-28 22:38:03 -0700166 if ('{' == m_expr[index]) {
167 while ('}' != m_expr[index]) {
Alexander Afanasyev36b84cf2014-02-17 19:34:18 -0800168 index++;
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -0700169 if (index == exprSize)
Alexander Afanasyev36b84cf2014-02-17 19:34:18 -0800170 break;
171 }
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -0700172 if (index == exprSize)
Davide Pesavento45ab9a92017-11-05 19:34:31 -0500173 BOOST_THROW_EXCEPTION(Error("Missing right brace bracket"));
Alexander Afanasyev36b84cf2014-02-17 19:34:18 -0800174 else
175 return ++index;
176 }
177 else {
178 return index;
179 }
180}
181
Alexander Afanasyev36b84cf2014-02-17 19:34:18 -0800182} // namespace ndn
183
184#endif // NDN_UTIL_REGEX_REGEX_PATTERN_LIST_MATCHER_HPP