regExpCxx.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) 2017-2019 OpenCFD Ltd.
9 -------------------------------------------------------------------------------
10 License
11  This file is part of OpenFOAM.
12 
13  OpenFOAM is free software: you can redistribute it and/or modify it
14  under the terms of the GNU General Public License as published by
15  the Free Software Foundation, either version 3 of the License, or
16  (at your option) any later version.
17 
18  OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
19  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
20  FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
21  for more details.
22 
23  You should have received a copy of the GNU General Public License
24  along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
25 
26 \*---------------------------------------------------------------------------*/
27 
28 #include "regExpCxx.H"
29 #include "debug.H"
30 #include "error.H"
31 
32 // * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
33 
35 
36 
37 // * * * * * * * * * * * * * * * Local Functions * * * * * * * * * * * * * * //
38 
39 namespace
40 {
41 
42 static std::string error_string(const std::regex_error& err)
43 {
44  switch (err.code())
45  {
46  case std::regex_constants::error_collate :
47  return "invalid collating element name";
48  break;
49 
50  case std::regex_constants::error_ctype :
51  return "invalid character class name";
52  break;
53 
54  case std::regex_constants::error_escape :
55  return "invalid escaped character or a trailing escape";
56  break;
57 
58  case std::regex_constants::error_backref :
59  return "invalid back reference";
60  break;
61 
62  case std::regex_constants::error_brack :
63  return "mismatched [ and ]";
64  break;
65 
66  case std::regex_constants::error_paren :
67  return "mismatched ( and )";
68  break;
69 
70  case std::regex_constants::error_brace :
71  return "mismatched { and }";
72  break;
73 
74  case std::regex_constants::error_badbrace :
75  return "invalid range in a {..}";
76  break;
77 
78  case std::regex_constants::error_range :
79  return "invalid [..] character range";
80  break;
81 
82  case std::regex_constants::error_space :
83  return "memory error";
84  break;
85 
86  case std::regex_constants::error_badrepeat :
87  return "bad '*?+{' repeat";
88  break;
89 
90  case std::regex_constants::error_complexity :
91  return "expression too complex";
92  break;
93 
94  case std::regex_constants::error_stack :
95  return "memory stack error";
96  break;
97 
98  default:
99  break;
100 
101  }
102 
103  return "";
104 }
105 
106 } // End anonymous namespace
107 
108 
109 // * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * * //
110 
111 bool Foam::regExpCxx::set(const char* pattern, bool ignoreCase)
112 {
113  clear(); // Also sets ok_ = false
114 
115  size_t len = (pattern ? strlen(pattern) : 0);
116 
117  // Avoid nullptr and zero-length patterns
118  if (!len)
119  {
120  return false;
121  }
122 
123  std::regex::flag_type flags = syntax();
124  if (ignoreCase)
125  {
126  flags |= std::regex::icase;
127  }
128 
129  const char* pat = pattern;
130 
131  // Has embedded ignore-case prefix?
132  if (len >= 4 && !strncmp(pattern, "(?i)", 4))
133  {
134  flags |= std::regex::icase;
135  pat += 4;
136  len -= 4;
137  }
138 
139  if (len)
140  {
141  try
142  {
143  re_.assign(pat, flags);
144  ok_ = true;
145  }
146  catch (const std::regex_error& err)
147  {
149  << "Failed to compile regular expression '"
150  << pattern << "'" << nl
151  << err.what() << ": " << error_string(err).c_str() << nl
152  << exit(FatalError);
153  }
154  }
155 
156  return ok_;
157 }
158 
159 
160 bool Foam::regExpCxx::set(const std::string& pattern, bool ignoreCase)
161 {
162  clear(); // Also sets ok_ = false
163 
164  auto len = pattern.size();
165 
166  // Avoid zero-length patterns
167  if (!len)
168  {
169  return false;
170  }
171 
172  std::regex::flag_type flags = syntax();
173  if (ignoreCase)
174  {
175  flags |= std::regex::icase;
176  }
177 
178  auto pat = pattern.begin();
179 
180  // Has embedded ignore-case prefix?
181  if (len >= 4 && !pattern.compare(0, 4, "(?i)"))
182  {
183  flags |= std::regex::icase;
184  pat += 4;
185  len -= 4;
186  }
187 
188  if (len)
189  {
190  try
191  {
192  re_.assign(pat, pattern.end(), flags);
193  ok_ = true;
194  }
195  catch (const std::regex_error& err)
196  {
198  << "Failed to compile regular expression '"
199  << pattern.c_str() << "'" << nl
200  << err.what() << ": " << error_string(err).c_str() << nl
201  << exit(FatalError);
202  }
203  }
204 
205  return ok_;
206 }
207 
208 
209 // ************************************************************************* //
regExpCxx.H
debug.H
Foam::regExpCxx::set
bool set(const char *pattern, bool ignoreCase=false)
Compile pattern into a regular expression, optionally ignore case.
Definition: regExpCxx.C:111
error.H
Foam::debug::optimisationSwitch
int optimisationSwitch(const char *name, const int deflt=0)
Lookup optimisation switch or add default value.
Definition: debug.C:237
Foam::FatalError
error FatalError
Foam::exit
errorManipArg< error, int > exit(error &err, const int errNo=1)
Definition: errorManip.H:130
Foam::regExpCxx::clear
bool clear()
Clear expression.
Definition: regExpCxxI.H:141
FatalErrorInFunction
#define FatalErrorInFunction
Report an error message using Foam::FatalError.
Definition: error.H:381
clear
patchWriters clear()
Foam::nl
constexpr char nl
Definition: Ostream.H:385
Foam::regExpCxx::grammar
static int grammar
The default grammar (extended | ECMAScript).
Definition: regExpCxx.H:99