regExp.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 | Copyright (C) 2011-2016 OpenFOAM Foundation
6  \\/ M anipulation |
7 -------------------------------------------------------------------------------
8 License
9  This file is part of OpenFOAM.
10 
11  OpenFOAM is free software: you can redistribute it and/or modify it
12  under the terms of the GNU General Public License as published by
13  the Free Software Foundation, either version 3 of the License, or
14  (at your option) any later version.
15 
16  OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
17  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
18  FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
19  for more details.
20 
21  You should have received a copy of the GNU General Public License
22  along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
23 
24 \*---------------------------------------------------------------------------*/
25 
26 #include "regExp.H"
27 #include "string.H"
28 #include "List.H"
29 
30 // * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
31 
32 template<class StringType>
33 bool Foam::regExp::matchGrouping
34 (
35  const std::string& str,
36  List<StringType>& groups
37 ) const
38 {
39  if (preg_ && str.size())
40  {
41  size_t nmatch = ngroups() + 1;
42  regmatch_t pmatch[nmatch];
43 
44  // Also verify that the entire string was matched.
45  // pmatch[0] is the entire match
46  // pmatch[1..] are the (...) sub-groups
47  if
48  (
49  regexec(preg_, str.c_str(), nmatch, pmatch, 0) == 0
50  && (pmatch[0].rm_so == 0 && pmatch[0].rm_eo == label(str.size()))
51  )
52  {
53  groups.setSize(ngroups());
54  label groupI = 0;
55 
56  for (size_t matchI = 1; matchI < nmatch; matchI++)
57  {
58  if (pmatch[matchI].rm_so != -1 && pmatch[matchI].rm_eo != -1)
59  {
60  groups[groupI] = str.substr
61  (
62  pmatch[matchI].rm_so,
63  pmatch[matchI].rm_eo - pmatch[matchI].rm_so
64  );
65  }
66  else
67  {
68  groups[groupI].clear();
69  }
70  groupI++;
71  }
72 
73  return true;
74  }
75  }
76 
77  groups.clear();
78  return false;
79 }
80 
81 
82 // * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
83 
85 :
86  preg_(0)
87 {}
88 
89 
90 Foam::regExp::regExp(const char* pattern, const bool ignoreCase)
91 :
92  preg_(0)
93 {
94  set(pattern, ignoreCase);
95 }
96 
97 
98 Foam::regExp::regExp(const std::string& pattern, const bool ignoreCase)
99 :
100  preg_(0)
101 {
102  set(pattern.c_str(), ignoreCase);
103 }
104 
105 
106 // * * * * * * * * * * * * * * * * Destructor * * * * * * * * * * * * * * * //
107 
109 {
110  clear();
111 }
112 
113 
114 // * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * * //
115 
116 void Foam::regExp::set(const char* pattern, const bool ignoreCase) const
117 {
118  clear();
119 
120  // Avoid nullptr and zero-length patterns
121  if (pattern && *pattern)
122  {
123  int cflags = REG_EXTENDED;
124  if (ignoreCase)
125  {
126  cflags |= REG_ICASE;
127  }
128 
129  const char* pat = pattern;
130 
131  // Check for embedded prefix for ignore-case
132  // this is the only embedded prefix we support
133  // - a simple check is sufficient
134  if (!strncmp(pattern, "(?i)", 4))
135  {
136  cflags |= REG_ICASE;
137  pat += 4;
138 
139  // avoid zero-length patterns
140  if (!*pat)
141  {
142  return;
143  }
144  }
145 
146  preg_ = new regex_t;
147  int err = regcomp(preg_, pat, cflags);
148 
149  if (err != 0)
150  {
151  char errbuf[200];
152  regerror(err, preg_, errbuf, sizeof(errbuf));
153 
155  << "Failed to compile regular expression '" << pattern << "'"
156  << nl << errbuf
157  << exit(FatalError);
158  }
159  }
160 }
161 
162 
163 void Foam::regExp::set(const std::string& pattern, const bool ignoreCase) const
164 {
165  return set(pattern.c_str(), ignoreCase);
166 }
167 
168 
170 {
171  if (preg_)
172  {
173  regfree(preg_);
174  delete preg_;
175  preg_ = 0;
176 
177  return true;
178  }
179 
180  return false;
181 }
182 
183 
184 std::string::size_type Foam::regExp::find(const std::string& str) const
185 {
186  if (preg_ && str.size())
187  {
188  size_t nmatch = 1;
189  regmatch_t pmatch[1];
190 
191  if (regexec(preg_, str.c_str(), nmatch, pmatch, 0) == 0)
192  {
193  return pmatch[0].rm_so;
194  }
195  }
196 
197  return string::npos;
198 }
199 
200 
201 bool Foam::regExp::match(const std::string& str) const
202 {
203  if (preg_ && str.size())
204  {
205  size_t nmatch = 1;
206  regmatch_t pmatch[1];
207 
208  // Also verify that the entire string was matched
209  // pmatch[0] is the entire match
210  if
211  (
212  regexec(preg_, str.c_str(), nmatch, pmatch, 0) == 0
213  && (pmatch[0].rm_so == 0 && pmatch[0].rm_eo == label(str.size()))
214  )
215  {
216  return true;
217  }
218  }
219 
220  return false;
221 }
222 
223 
225 (
226  const std::string& str,
227  List<std::string>& groups
228 ) const
229 {
230  return matchGrouping(str, groups);
231 }
232 
233 
235 (
236  const std::string& str,
237  List<Foam::string>& groups
238 ) const
239 {
240  return matchGrouping(str, groups);
241 }
242 
243 
244 // * * * * * * * * * * * * * * Member Operators * * * * * * * * * * * * * * //
245 
246 void Foam::regExp::operator=(const char* pat)
247 {
248  set(pat);
249 }
250 
251 
252 void Foam::regExp::operator=(const std::string& pat)
253 {
254  set(pat);
255 }
256 
257 
258 // ************************************************************************* //
bool clear() const
Release precompiled expression.
Definition: regExp.C:169
intWM_LABEL_SIZE_t label
A label is an int32_t or int64_t as specified by the pre-processor macro WM_LABEL_SIZE.
Definition: label.H:59
bool match(const std::string &) const
Return true if it matches the entire string.
Definition: regExp.C:201
errorManipArg< error, int > exit(error &err, const int errNo=1)
Definition: errorManip.H:124
error FatalError
#define FatalErrorInFunction
Report an error message using Foam::FatalError.
Definition: error.H:319
A 1D array of objects of type <T>, where the size of the vector is known and used for subscript bound...
Definition: HashTable.H:60
~regExp()
Destructor.
Definition: regExp.C:108
graph_traits< Graph >::vertices_size_type size_type
Definition: SloanRenumber.C:73
static const char nl
Definition: Ostream.H:262
int ngroups() const
Return the number of (groups)
Definition: regExp.H:143
std::string::size_type find(const std::string &str) const
Find position within string.
Definition: regExp.C:184
regExp()
Construct null.
Definition: regExp.C:84
void set(const char *, const bool ignoreCase=false) const
Compile pattern into a regular expression,.
Definition: regExp.C:116