ndn-cxx: NDN C++ Library 0.9.0-33-g832ea91d
Loading...
Searching...
No Matches
regex-repeat-matcher.cpp
Go to the documentation of this file.
1/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
2/*
3 * Copyright (c) 2013-2025 Regents of the University of California.
4 *
5 * This file is part of ndn-cxx library (NDN C++ library with eXperimental eXtensions).
6 *
7 * 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.
20 *
21 * @author Yingdi Yu <http://irl.cs.ucla.edu/~yingdi/>
22 */
23
27
28#include <regex>
29
30namespace ndn {
31
33 shared_ptr<RegexBackrefManager> backrefManager,
34 size_t indicator)
35 : RegexMatcher(expr, EXPR_REPEAT_PATTERN, std::move(backrefManager))
36 , m_indicator(indicator)
37{
38 compile();
39}
40
41void
42RegexRepeatMatcher::compile()
43{
44 if ('(' == m_expr[0]) {
45 auto matcher = make_shared<RegexBackrefMatcher>(m_expr.substr(0, m_indicator),
47 m_backrefManager->pushRef(matcher);
48 matcher->compile();
49 m_matchers.push_back(std::move(matcher));
50 }
51 else {
52 m_matchers.push_back(make_shared<RegexComponentSetMatcher>(m_expr.substr(0, m_indicator),
54 }
55
56 parseRepetition();
57}
58
59void
60RegexRepeatMatcher::parseRepetition()
61{
62 constexpr size_t MAX_REPETITIONS = std::numeric_limits<size_t>::max();
63 size_t exprSize = m_expr.size();
64
65 if (exprSize == m_indicator) {
66 m_repeatMin = 1;
67 m_repeatMax = 1;
68 }
69 else if (exprSize == m_indicator + 1) {
70 switch (m_expr[m_indicator]) {
71 case '?':
72 m_repeatMin = 0;
73 m_repeatMax = 1;
74 break;
75 case '+':
76 m_repeatMin = 1;
77 m_repeatMax = MAX_REPETITIONS;
78 break;
79 case '*':
80 m_repeatMin = 0;
81 m_repeatMax = MAX_REPETITIONS;
82 break;
83 default:
84 NDN_THROW(Error("Unrecognized quantifier '"s + m_expr[m_indicator] + "' in regex: " + m_expr));
85 }
86 }
87 else {
88 std::string repeatStruct = m_expr.substr(m_indicator, exprSize - m_indicator);
89 size_t rsSize = repeatStruct.size();
90
91 try {
92 if (std::regex_match(repeatStruct, std::regex("\\{[0-9]+,[0-9]+\\}"))) {
93 size_t separator = repeatStruct.find_first_of(',', 0);
94 m_repeatMin = std::stoul(repeatStruct.substr(1, separator - 1));
95 m_repeatMax = std::stoul(repeatStruct.substr(separator + 1, rsSize - separator - 2));
96 if (m_repeatMin > m_repeatMax) {
97 NDN_THROW(Error("Invalid number of repetitions '" + repeatStruct + "' in regex: " + m_expr));
98 }
99 }
100 else if (std::regex_match(repeatStruct, std::regex("\\{,[0-9]+\\}"))) {
101 size_t separator = repeatStruct.find_first_of(',', 0);
102 m_repeatMin = 0;
103 m_repeatMax = std::stoul(repeatStruct.substr(separator + 1, rsSize - separator - 2));
104 }
105 else if (std::regex_match(repeatStruct, std::regex("\\{[0-9]+,\\}"))) {
106 size_t separator = repeatStruct.find_first_of(',', 0);
107 m_repeatMin = std::stoul(repeatStruct.substr(1, separator));
108 m_repeatMax = MAX_REPETITIONS;
109 }
110 else if (std::regex_match(repeatStruct, std::regex("\\{[0-9]+\\}"))) {
111 m_repeatMin = std::stoul(repeatStruct.substr(1, rsSize - 1));
112 m_repeatMax = m_repeatMin;
113 }
114 else {
115 NDN_THROW(Error("Invalid quantifier '" + repeatStruct + "' in regex: " + m_expr));
116 }
117 }
118 // std::stoul can throw invalid_argument or out_of_range, both are derived from logic_error
119 catch (const std::logic_error&) {
120 NDN_THROW(Error("Invalid number of repetitions '" + repeatStruct + "' in regex: " + m_expr));
121 }
122 }
123}
124
125bool
126RegexRepeatMatcher::match(const Name& name, size_t offset, size_t len)
127{
128 m_matchResult.clear();
129
130 if (m_repeatMin == 0 && len == 0) {
131 return true;
132 }
133
134 if (recursiveMatch(0, name, offset, len)) {
135 for (size_t i = offset; i < offset + len; i++) {
136 m_matchResult.push_back(name.get(i));
137 }
138 return true;
139 }
140
141 return false;
142}
143
144bool
145RegexRepeatMatcher::recursiveMatch(size_t repeat, const Name& name, size_t offset, size_t len)
146{
147 if (0 < len && repeat >= m_repeatMax) {
148 return false;
149 }
150
151 if (0 == len && repeat < m_repeatMin) {
152 return false;
153 }
154
155 if (0 == len && repeat >= m_repeatMin) {
156 return true;
157 }
158
159 const auto& matcher = m_matchers[0];
160 ssize_t tried = static_cast<ssize_t>(len);
161 while (tried >= 0) {
162 if (matcher->match(name, offset, tried) &&
163 recursiveMatch(repeat + 1, name, offset + tried, len - tried)) {
164 return true;
165 }
166 tried--;
167 }
168
169 return false;
170}
171
172} // namespace ndn
Represents an absolute name.
Definition name.hpp:45
const Component & get(ssize_t i) const noexcept
Returns an immutable reference to the component at the specified index.
Definition name.hpp:192
std::vector< name::Component > m_matchResult
shared_ptr< RegexBackrefManager > m_backrefManager
const std::string m_expr
std::vector< shared_ptr< RegexMatcher > > m_matchers
bool match(const Name &name, size_t offset, size_t len) override
RegexRepeatMatcher(const std::string &expr, shared_ptr< RegexBackrefManager > backrefManager, size_t indicator)
#define NDN_THROW(e)
Definition exception.hpp:56
Definition data.cpp:25
STL namespace.