regExpPosix.C
Go to the documentation of this file.
1/*---------------------------------------------------------------------------*\
2 ========= |
3 \\ / F ield | OpenFOAM: The Open Source CFD Toolbox
4 \\ / O peration |
5 \\ / A nd | www.openfoam.com
6 \\/ M anipulation |
7-------------------------------------------------------------------------------
8 Copyright (C) 2011-2016 OpenFOAM Foundation
9 Copyright (C) 2018-2021 OpenCFD Ltd.
10-------------------------------------------------------------------------------
11License
12 This file is part of OpenFOAM.
13
14 OpenFOAM is free software: you can redistribute it and/or modify it
15 under the terms of the GNU General Public License as published by
16 the Free Software Foundation, either version 3 of the License, or
17 (at your option) any later version.
18
19 OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
20 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
21 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
22 for more details.
23
24 You should have received a copy of the GNU General Public License
25 along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
26
27\*---------------------------------------------------------------------------*/
28
29#include "regExpPosix.H"
30#include "SubStrings.H"
31#include "error.H"
32
33// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
34
36
37
38// * * * * * * * * * * * * * * * Local Functions * * * * * * * * * * * * * * //
39
40namespace
41{
42
43// Matched entire length
44static inline bool fullMatch(const regmatch_t& m, const regoff_t len)
45{
46 return (m.rm_so == 0 && m.rm_eo == len);
47}
48
49} // End anonymous namespace
50
51
52// * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
53
54bool Foam::regExpPosix::set_pattern
55(
56 const char* pattern,
57 size_t len,
58 bool ignoreCase
59)
60{
61 clear(); // Also sets ctrl_ = 0
62
63 const char* pat = pattern;
64 bool doNegate = false;
65
66 // Handle known embedded prefixes
67 if (len > 2 && pat[0] == '(' && pat[1] == '?')
68 {
69 pat += 2;
70 len -= 2;
71
72 for (bool done = false; !done && len; ++pat, --len)
73 {
74 switch (*pat)
75 {
76 case '!':
77 {
78 // Negated (inverted) match
79 doNegate = true;
80 break;
81 }
82 case 'i':
83 {
84 // Ignore-case
85 ignoreCase = true;
86 break;
87 }
88 case ')':
89 {
90 // End of prefix parsing
91 done = true;
92 break;
93 }
94 }
95 }
96 }
97
98 // Avoid zero-length patterns
99 if (len)
100 {
101 int flags = REG_EXTENDED;
102 if (ignoreCase)
103 {
104 flags |= REG_ICASE;
105 }
106
107 {
108 preg_ = new regex_t;
109 int err = regcomp(preg_, pat, flags);
110
111 if (err == 0)
112 {
113 ctrl_ = (doNegate ? ctrlType::NEGATED : ctrlType::NORMAL);
114 return true;
115 }
116 else
117 {
118 char errbuf[200];
119 regerror(err, preg_, errbuf, sizeof(errbuf));
120
122 << "Failed to compile regular expression '"
123 << pattern << "'\n" << errbuf
124 << exit(FatalError);
125 }
126 }
127 }
128
129 return false;
130}
131
132
133// * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * * //
134
136{
137 ctrl_ = 0;
138
139 if (preg_)
140 {
141 regfree(preg_);
142 delete preg_;
143 preg_ = nullptr;
144 return true;
145 }
146
147 return false;
148}
149
150
151std::string::size_type Foam::regExpPosix::find(const std::string& text) const
152{
153 // Find with negated is probably not very reliable...
154 if (!preg_ || !ctrl_)
155 {
156 // Undefined: never matches
157 return std::string::npos;
158 }
159 else if (text.empty())
160 {
161 if (ctrl_ == ctrlType::NEGATED)
162 {
163 return 0; // No match - pretend it starts at position 0
164 }
165 else
166 {
167 return std::string::npos;
168 }
169 }
170 else
171 {
172 const size_t nmatch = 1;
173 regmatch_t pmatch[1];
174
175 const bool ok = (regexec(preg_, text.c_str(), nmatch, pmatch, 0) == 0);
176
177 if (ctrl_ == ctrlType::NEGATED)
178 {
179 if (!ok)
180 {
181 return 0; // No match - claim that is starts at position 0
182 }
183 }
184 else if (ok)
185 {
186 return pmatch[0].rm_so;
187 }
188 }
189
190 return std::string::npos;
191}
192
193
194bool Foam::regExpPosix::match(const std::string& text) const
195{
196 bool ok = false;
197
198 if (!preg_ || !ctrl_)
199 {
200 // Undefined: never matches
201 return false;
202 }
203
204 const auto len = text.length();
205
206 if (len)
207 {
208 const size_t nmatch = 1;
209 regmatch_t pmatch[1];
210
211 // Verify that the entire string was matched
212 // - [0] is the entire match result
213 ok =
214 (
215 regexec(preg_, text.c_str(), nmatch, pmatch, 0) == 0
216 && fullMatch(pmatch[0], len)
217 );
218 }
219
220 return (ctrl_ == ctrlType::NEGATED ? !ok : ok);
221}
222
223
225(
226 const std::string& text,
228) const
229{
230 matches.clear();
231
232 // Probably does not make sense for negated pattern...
233 if (negated())
234 {
235 return match(text);
236 }
237
238 const auto len = text.size();
239 if (preg_ && len)
240 {
241 const size_t nmatch = ngroups() + 1;
242 regmatch_t pmatch[nmatch];
243
244 // Verify that the entire string was matched
245 // - [0] is the entire match result
246 // - [1..] are the match groups (1..)
247 if
248 (
249 regexec(preg_, text.c_str(), nmatch, pmatch, 0) != 0
250 || !fullMatch(pmatch[0], len)
251 )
252 {
253 return false;
254 }
255
256 matches.reserve(nmatch);
257
258 for (size_t matchi = 0; matchi < nmatch; ++matchi)
259 {
260 const auto& mat = pmatch[matchi];
261
262 if (mat.rm_so != -1 && mat.rm_eo != -1)
263 {
264 matches.append
265 (
266 text.cbegin() + mat.rm_so,
267 text.cbegin() + mat.rm_eo
268 );
269 }
270 else
271 {
272 // This may be misleading...
273 matches.append(text.cbegin(), text.cbegin());
274 }
275 }
276
277 return true;
278 }
279
280 return false;
281}
282
283
284// ************************************************************************* //
Sub-ranges of a string with a structure similar to std::match_results, but without the underlying reg...
Definition: SubStrings.H:54
void append(const typename StringType::const_iterator &b, const typename StringType::const_iterator &e)
Append sub-string defined by begin/end iterators.
Definition: SubStrings.H:92
std::string::size_type find(const std::string &text) const
Find position within the text.
Definition: regExpPosix.C:151
bool match(const std::string &text) const
True if the regex matches the entire text.
Definition: regExpPosix.C:194
bool clear()
Clear expression.
Definition: regExpPosix.C:135
static int grammar
Grammar (unused) - for compatibility with Foam::regExpCxx.
Definition: regExpPosix.H:118
#define FatalErrorInFunction
Report an error message using Foam::FatalError.
Definition: error.H:453
error FatalError
errorManipArg< error, int > exit(error &err, const int errNo=1)
Definition: errorManip.H:130