2020
2121#include " regex.h"
2222
23+ #include < regex>
2324#include < utility>
2425
2526#ifdef _WIN32
@@ -188,15 +189,15 @@ namespace {
188189 std::string PcreRegex::compile ()
189190 {
190191 if (mRe )
191- return " pcre_compile failed: regular expression has already been compiled" ;
192+ return " regular expression has already been compiled" ;
192193
193194 const char *pcreCompileErrorStr = nullptr ;
194195 int erroffset = 0 ;
195196 pcre * const re = pcre_compile (mPattern .c_str (),0 ,&pcreCompileErrorStr,&erroffset,nullptr );
196197 if (!re) {
197198 if (pcreCompileErrorStr)
198- return " pcre_compile failed: " + std::string ( pcreCompileErrorStr) ;
199- return " pcre_compile failed: unknown error" ;
199+ return pcreCompileErrorStr;
200+ return " unknown error" ;
200201 }
201202
202203 // Optimize the regex, but only if PCRE_CONFIG_JIT is available
@@ -209,7 +210,7 @@ namespace {
209210 if (pcreStudyErrorStr) {
210211 // pcre_compile() worked, but pcre_study() returned an error. Free the resources allocated by pcre_compile().
211212 pcre_free (re);
212- return " pcre_study failed: " + std::string (pcreStudyErrorStr);
213+ return std::string (pcreStudyErrorStr) + " (pcre_study) " ;
213214 }
214215 mExtra = pcreExtra;
215216#endif
@@ -222,7 +223,7 @@ namespace {
222223 std::string PcreRegex::match (const std::string& str, const MatchFn& match) const
223224 {
224225 if (!mRe )
225- return " pcre_exec failed: regular expression has not been compiled yet" ;
226+ return " regular expression has not been compiled yet" ;
226227
227228 int pos = 0 ;
228229 int ovector[30 ]= {0 };
@@ -231,7 +232,7 @@ namespace {
231232 if (pcreExecRet == PCRE_ERROR_NOMATCH)
232233 return " " ;
233234 if (pcreExecRet < 0 ) {
234- return " pcre_exec failed (pos: " + std::to_string (pos) + " ): " + pcreErrorCodeToString (pcreExecRet) ;
235+ return pcreErrorCodeToString (pcreExecRet) + " (pos: " + std::to_string (pos) + " )" ;
235236 }
236237 const auto pos1 = static_cast <unsigned int >(ovector[0 ]);
237238 const auto pos2 = static_cast <unsigned int >(ovector[1 ]);
@@ -246,10 +247,69 @@ namespace {
246247 }
247248}
248249
249- std::shared_ptr<Regex> Regex::create (std::string pattern, std::string& err)
250+ namespace {
251+ class StdRegex : public Regex
252+ {
253+ public:
254+ explicit StdRegex (std::string pattern)
255+ : mPattern(std::move(pattern))
256+ {}
257+
258+ std::string compile ()
259+ {
260+ if (mCompiled )
261+ return " regular expression has already been compiled" ;
262+
263+ try {
264+ mRegex = std::regex (mPattern );
265+ } catch (const std::exception& e) {
266+ return e.what ();
267+ }
268+ mCompiled = true ;
269+ return " " ;
270+ }
271+
272+ std::string match (const std::string& str, const MatchFn& matchFn) const override
273+ {
274+ if (!mCompiled )
275+ return " regular expression has not been compiled yet" ;
276+
277+ auto I = std::sregex_iterator (str.cbegin (), str.cend (), mRegex );
278+ const auto E = std::sregex_iterator ();
279+ while (I != E)
280+ {
281+ const std::smatch& match = *I;
282+ matchFn (match.position (), match.position () + match.length ());
283+ ++I;
284+ }
285+ return " " ;
286+ }
287+
288+ private:
289+ std::string mPattern ;
290+ std::regex mRegex ;
291+ bool mCompiled {};
292+ };
293+ }
294+
295+ template <typename T>
296+ static T* createAndCompileRegex (std::string pattern, std::string& err)
250297{
251- auto * regex = new PcreRegex (std::move (pattern));
298+ T * regex = new T (std::move (pattern));
252299 err = regex->compile ();
300+ return regex;
301+ }
302+
303+ std::shared_ptr<Regex> Regex::create (std::string pattern, Engine engine, std::string& err)
304+ {
305+ Regex* regex = nullptr ;
306+ if (engine == Engine::Pcre)
307+ regex = createAndCompileRegex<PcreRegex>(std::move (pattern), err);
308+ else if (engine == Engine::Std)
309+ regex = createAndCompileRegex<StdRegex>(std::move (pattern), err);
310+ else {
311+ err = " unknown regular expression engine" ;
312+ }
253313 if (!err.empty ()) {
254314 delete regex;
255315 return nullptr ;
0 commit comments