ndn-cxx: NDN C++ Library 0.9.0-33-g832ea91d
Loading...
Searching...
No Matches
regex-top-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-2023 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
25
28
29#include <boost/lexical_cast.hpp>
30
31namespace ndn {
32
33RegexTopMatcher::RegexTopMatcher(const std::string& expr, const std::string& expand)
34 : RegexMatcher(expr, EXPR_TOP)
35 , m_expand(expand)
36 , m_isSecondaryUsed(false)
37{
38 m_primaryBackrefManager = make_shared<RegexBackrefManager>();
39 m_secondaryBackrefManager = make_shared<RegexBackrefManager>();
40 compile();
41}
42
43void
44RegexTopMatcher::compile()
45{
46 std::string expr = m_expr;
47
48 if ('$' != expr[expr.size() - 1])
49 expr = expr + "<.*>*";
50 else
51 expr = expr.substr(0, expr.size() - 1);
52
53 if ('^' != expr[0]) {
54 m_secondaryMatcher = make_shared<RegexPatternListMatcher>("<.*>*" + expr,
55 m_secondaryBackrefManager);
56 }
57 else {
58 expr = expr.substr(1, expr.size() - 1);
59 }
60
61 m_primaryMatcher = make_shared<RegexPatternListMatcher>(expr, m_primaryBackrefManager);
62}
63
64bool
66{
67 m_isSecondaryUsed = false;
68
69 m_matchResult.clear();
70
71 if (m_primaryMatcher->match(name, 0, name.size())) {
72 m_matchResult = m_primaryMatcher->getMatchResult();
73 return true;
74 }
75 else {
76 if (m_secondaryMatcher != nullptr && m_secondaryMatcher->match(name, 0, name.size())) {
77 m_matchResult = m_secondaryMatcher->getMatchResult();
78 m_isSecondaryUsed = true;
79 return true;
80 }
81 return false;
82 }
83}
84
85bool
86RegexTopMatcher::match(const Name& name, size_t, size_t)
87{
88 return match(name);
89}
90
91Name
92RegexTopMatcher::expand(const std::string& expandStr)
93{
94 auto backrefManager = m_isSecondaryUsed ? m_secondaryBackrefManager : m_primaryBackrefManager;
95 size_t backrefNo = backrefManager->size();
96
97 std::string expand;
98 if (!expandStr.empty())
99 expand = expandStr;
100 else
101 expand = m_expand;
102
103 Name result;
104 size_t offset = 0;
105 while (offset < expand.size()) {
106 std::string item = getItemFromExpand(expand, offset);
107 if (item[0] == '<') {
108 result.append(item.substr(1, item.size() - 2));
109 }
110 if (item[0] == '\\') {
111 size_t index = boost::lexical_cast<size_t>(item.substr(1, item.size() - 1));
112 if (index == 0) {
113 for (const auto& i : m_matchResult)
114 result.append(i);
115 }
116 else if (index <= backrefNo) {
117 for (const auto& i : backrefManager->getBackref(index - 1)->getMatchResult())
118 result.append(i);
119 }
120 else
121 NDN_THROW(Error("Exceeded the range of back reference"));
122 }
123 }
124
125 return result;
126}
127
128std::string
129RegexTopMatcher::getItemFromExpand(const std::string& expand, size_t& offset)
130{
131 size_t begin = offset;
132
133 if (expand[offset] == '\\') {
134 offset++;
135 if (offset >= expand.size())
136 NDN_THROW(Error("Wrong format of expand string"));
137
138 while (expand[offset] <= '9' and expand[offset] >= '0') {
139 offset++;
140 if (offset > expand.size())
141 NDN_THROW(Error("Wrong format of expand string"));
142 }
143 if (offset > begin + 1)
144 return expand.substr(begin, offset - begin);
145 else
146 NDN_THROW(Error("Wrong format of expand string"));
147 }
148 else if (expand[offset] == '<') {
149 offset++;
150 if (offset >= expand.size())
151 NDN_THROW(Error("Wrong format of expand string"));
152
153 size_t left = 1;
154 size_t right = 0;
155 while (right < left) {
156 if (expand[offset] == '<')
157 left++;
158 if (expand[offset] == '>')
159 right++;
160 offset++;
161 if (offset >= expand.size())
162 NDN_THROW(Error("Wrong format of expand string"));
163 }
164 return expand.substr(begin, offset - begin);
165 }
166 else
167 NDN_THROW(Error("Wrong format of expand string"));
168}
169
170shared_ptr<RegexTopMatcher>
171RegexTopMatcher::fromName(const Name& name, bool hasAnchor)
172{
173 std::string regexStr("^");
174
175 for (const auto& i : name) {
176 regexStr.append("<");
177 regexStr.append(convertSpecialChar(i.toUri()));
178 regexStr.append(">");
179 }
180
181 if (hasAnchor)
182 regexStr.append("$");
183
184 return make_shared<RegexTopMatcher>(regexStr);
185}
186
187std::string
188RegexTopMatcher::convertSpecialChar(const std::string& str)
189{
190 std::string newStr;
191
192 for (size_t i = 0; i < str.size(); i++) {
193 char c = str[i];
194 switch (c) {
195 case '.':
196 case '[':
197 case '{':
198 case '}':
199 case '(':
200 case ')':
201 case '\\':
202 case '*':
203 case '+':
204 case '?':
205 case '|':
206 case '^':
207 case '$':
208 newStr.push_back('\\');
209 [[fallthrough]];
210 default:
211 newStr.push_back(c);
212 break;
213 }
214 }
215
216 return newStr;
217}
218
219} // namespace ndn
Represents an absolute name.
Definition name.hpp:45
Name & append(const Component &component)
Append a name component.
Definition name.hpp:308
size_t size() const noexcept
Returns the number of components.
Definition name.hpp:180
std::vector< name::Component > m_matchResult
const std::string m_expr
static shared_ptr< RegexTopMatcher > fromName(const Name &name, bool hasAnchor=false)
bool match(const Name &name)
virtual Name expand(const std::string &expand="")
RegexTopMatcher(const std::string &expr, const std::string &expand="")
#define NDN_THROW(e)
Definition exception.hpp:56
Definition data.cpp:25