@@ -156,115 +156,105 @@ namespace {
156156 }
157157 return " unknown PCRE error " + std::to_string (pcreExecRet);
158158 }
159- }
160-
161- class Regex ::Data
162- {
163- public:
164- explicit Data (std::string pattern)
165- : mPattern(std::move(pattern))
166- {}
167159
168- ~Data ()
160+ class PcreRegex : public Regex
169161 {
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+ }
177177 }
178- }
179178
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 ;
182181
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+ };
188187
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" ;
193192
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+ }
202201
203- // Optimize the regex, but only if PCRE_CONFIG_JIT is available
202+ // Optimize the regex, but only if PCRE_CONFIG_JIT is available
204203#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;
216215#endif
217216
218- mRe = re;
217+ mRe = re;
219218
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+ }
239221
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" ;
241226
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 ]);
245238
246- return " " ;
247- }
239+ match (pos1, pos2);
248240
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+ }
253244
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+ }
261247}
262248
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)
264250{
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);
268258}
269259
270260#endif // HAVE_RULES
0 commit comments