@@ -156,115 +156,105 @@ namespace {
156
156
}
157
157
return " unknown PCRE error " + std::to_string (pcreExecRet);
158
158
}
159
- }
160
-
161
- class Regex ::Data
162
- {
163
- public:
164
- explicit Data (std::string pattern)
165
- : mPattern(std::move(pattern))
166
- {}
167
159
168
- ~Data ()
160
+ class PcreRegex : public Regex
169
161
{
170
- if (mExtra ) {
171
- pcre_free (mExtra );
172
- mExtra = nullptr ;
173
- }
174
- if (mRe ) {
175
- pcre_free (mRe );
176
- mRe = nullptr ;
162
+ public:
163
+ explicit PcreRegex (std::string pattern)
164
+ : mPattern(std::move(pattern))
165
+ {}
166
+
167
+ ~PcreRegex () override
168
+ {
169
+ if (mExtra ) {
170
+ pcre_free (mExtra );
171
+ mExtra = nullptr ;
172
+ }
173
+ if (mRe ) {
174
+ pcre_free (mRe );
175
+ mRe = nullptr ;
176
+ }
177
177
}
178
- }
179
178
180
- std::string compile ();
181
- std::string match (const std::string& str, const MatchFn& match) const ;
179
+ std::string compile ();
180
+ std::string match (const std::string& str, const MatchFn& match) const override ;
182
181
183
- private:
184
- std::string mPattern ;
185
- pcre* mRe {};
186
- pcre_extra* mExtra {};
187
- };
182
+ private:
183
+ std::string mPattern ;
184
+ pcre* mRe {};
185
+ pcre_extra* mExtra {};
186
+ };
188
187
189
- std::string Regex::Data ::compile ()
190
- {
191
- if (mRe )
192
- return " pcre_compile failed: regular expression has already been compiled" ;
188
+ std::string PcreRegex ::compile ()
189
+ {
190
+ if (mRe )
191
+ return " pcre_compile failed: regular expression has already been compiled" ;
193
192
194
- const char *pcreCompileErrorStr = nullptr ;
195
- int erroffset = 0 ;
196
- pcre * const re = pcre_compile (mPattern .c_str (),0 ,&pcreCompileErrorStr,&erroffset,nullptr );
197
- if (!re) {
198
- if (pcreCompileErrorStr)
199
- return " pcre_compile failed: " + std::string (pcreCompileErrorStr);
200
- return " pcre_compile failed: unknown error" ;
201
- }
193
+ const char *pcreCompileErrorStr = nullptr ;
194
+ int erroffset = 0 ;
195
+ pcre * const re = pcre_compile (mPattern .c_str (),0 ,&pcreCompileErrorStr,&erroffset,nullptr );
196
+ if (!re) {
197
+ if (pcreCompileErrorStr)
198
+ return " pcre_compile failed: " + std::string (pcreCompileErrorStr);
199
+ return " pcre_compile failed: unknown error" ;
200
+ }
202
201
203
- // Optimize the regex, but only if PCRE_CONFIG_JIT is available
202
+ // Optimize the regex, but only if PCRE_CONFIG_JIT is available
204
203
#ifdef PCRE_CONFIG_JIT
205
- const char *pcreStudyErrorStr = nullptr ;
206
- pcre_extra * const pcreExtra = pcre_study (re, PCRE_STUDY_JIT_COMPILE, &pcreStudyErrorStr);
207
- // pcre_study() returns NULL for both errors and when it can not optimize the regex.
208
- // The last argument is how one checks for errors.
209
- // It is NULL if everything works, and points to an error string otherwise.
210
- if (pcreStudyErrorStr) {
211
- // pcre_compile() worked, but pcre_study() returned an error. Free the resources allocated by pcre_compile().
212
- pcre_free (re);
213
- return " pcre_study failed: " + std::string (pcreStudyErrorStr);
214
- }
215
- mExtra = pcreExtra;
204
+ const char *pcreStudyErrorStr = nullptr ;
205
+ pcre_extra * const pcreExtra = pcre_study (re, PCRE_STUDY_JIT_COMPILE, &pcreStudyErrorStr);
206
+ // pcre_study() returns NULL for both errors and when it can not optimize the regex.
207
+ // The last argument is how one checks for errors.
208
+ // It is NULL if everything works, and points to an error string otherwise.
209
+ if (pcreStudyErrorStr) {
210
+ // pcre_compile() worked, but pcre_study() returned an error. Free the resources allocated by pcre_compile().
211
+ pcre_free (re);
212
+ return " pcre_study failed: " + std::string (pcreStudyErrorStr);
213
+ }
214
+ mExtra = pcreExtra;
216
215
#endif
217
216
218
- mRe = re;
217
+ mRe = re;
219
218
220
- return " " ;
221
- }
222
-
223
- std::string Regex::Data::match (const std::string& str, const MatchFn& match) const
224
- {
225
- if (!mRe )
226
- return " pcre_exec failed: regular expression has not been compiled yet" ;
227
-
228
- int pos = 0 ;
229
- int ovector[30 ]= {0 };
230
- while (pos < static_cast <int >(str.size ())) {
231
- const int pcreExecRet = pcre_exec (mRe , mExtra , str.c_str (), static_cast <int >(str.size ()), pos, 0 , ovector, 30 );
232
- if (pcreExecRet == PCRE_ERROR_NOMATCH)
233
- return " " ;
234
- if (pcreExecRet < 0 ) {
235
- return std::string (" pcre_exec failed (pos: " + std::to_string (pos) + " ): " ) + pcreErrorCodeToString (pcreExecRet);
236
- }
237
- const auto pos1 = static_cast <unsigned int >(ovector[0 ]);
238
- const auto pos2 = static_cast <unsigned int >(ovector[1 ]);
219
+ return " " ;
220
+ }
239
221
240
- match (pos1, pos2);
222
+ std::string PcreRegex::match (const std::string& str, const MatchFn& match) const
223
+ {
224
+ if (!mRe )
225
+ return " pcre_exec failed: regular expression has not been compiled yet" ;
241
226
242
- // jump to the end of the match for the next pcre_exec
243
- pos = static_cast <int >(pos2);
244
- }
227
+ int pos = 0 ;
228
+ int ovector[30 ]= {0 };
229
+ while (pos < static_cast <int >(str.size ())) {
230
+ const int pcreExecRet = pcre_exec (mRe , mExtra , str.c_str (), static_cast <int >(str.size ()), pos, 0 , ovector, 30 );
231
+ if (pcreExecRet == PCRE_ERROR_NOMATCH)
232
+ return " " ;
233
+ if (pcreExecRet < 0 ) {
234
+ return std::string (" pcre_exec failed (pos: " + std::to_string (pos) + " ): " ) + pcreErrorCodeToString (pcreExecRet);
235
+ }
236
+ const auto pos1 = static_cast <unsigned int >(ovector[0 ]);
237
+ const auto pos2 = static_cast <unsigned int >(ovector[1 ]);
245
238
246
- return " " ;
247
- }
239
+ match (pos1, pos2);
248
240
249
- std::string Regex::compile (std::string pattern)
250
- {
251
- if (mData )
252
- return " regular expression has already been compiled" ;
241
+ // jump to the end of the match for the next pcre_exec
242
+ pos = static_cast <int >(pos2);
243
+ }
253
244
254
- auto * data = new Data (std::move (pattern));
255
- auto res = data->compile ();
256
- if (res.empty ())
257
- mData .reset (data);
258
- else
259
- delete data;
260
- return res;
245
+ return " " ;
246
+ }
261
247
}
262
248
263
- std::string Regex::match ( const std::string& str, const MatchFn& match) const
249
+ std::shared_ptr<Regex> Regex::create ( std::string pattern, std::string& err)
264
250
{
265
- if (!mData )
266
- return " regular expression hat not been compiled yet" ;
267
- return mData ->match (str, match);
251
+ auto * regex = new PcreRegex (std::move (pattern));
252
+ err = regex->compile ();
253
+ if (!err.empty ()) {
254
+ delete regex;
255
+ return nullptr ;
256
+ }
257
+ return std::shared_ptr<Regex>(regex);
268
258
}
269
259
270
260
#endif // HAVE_RULES
0 commit comments