2424
2525#include " pattern.h"
2626
27+ #include < tsutil/Regex.h>
28+
2729static void
2830replaceString (String &str, const String &from, const String &to)
2931{
@@ -40,6 +42,8 @@ replaceString(String &str, const String &from, const String &to)
4042
4143Pattern::Pattern () : _pattern(" " ), _replacement(" " ) {}
4244
45+ Pattern::~Pattern () = default ;
46+
4347/* *
4448 * @brief Initializes PCRE pattern by providing the subject and replacement strings.
4549 * @param pattern PCRE pattern, a string containing PCRE patterns, capturing groups.
@@ -49,8 +53,6 @@ Pattern::Pattern() : _pattern(""), _replacement("") {}
4953bool
5054Pattern::init (const String &pattern, const String &replacement, bool replace)
5155{
52- pcreFree ();
53-
5456 _pattern.assign (pattern);
5557 _replacement.assign (replacement);
5658 _replace = replace;
@@ -59,7 +61,7 @@ Pattern::init(const String &pattern, const String &replacement, bool replace)
5961
6062 if (!compile ()) {
6163 AccessControlDebug (" failed to initialize pattern:'%s', replacement:'%s'" , pattern.c_str (), replacement.c_str ());
62- pcreFree ();
64+ _re. reset ();
6365 return false ;
6466 }
6567
@@ -139,33 +141,12 @@ Pattern::getPattern()
139141bool
140142Pattern::empty () const
141143{
142- return _pattern.empty () || nullptr == _re;
143- }
144-
145- /* *
146- * @brief Frees PCRE library related resources.
147- */
148- void
149- Pattern::pcreFree ()
150- {
151- if (_re) {
152- pcre_free (_re);
153- _re = nullptr ;
154- }
155-
156- if (_extra) {
157- pcre_free (_extra);
158- _extra = nullptr ;
159- }
144+ return _pattern.empty () || !_re || _re->empty ();
160145}
161146
162147/* *
163148 * @brief Destructor, frees PCRE related resources.
164149 */
165- Pattern::~Pattern ()
166- {
167- pcreFree ();
168- }
169150
170151/* *
171152 * @brief Capture or capture-and-replace depending on whether a replacement string is specified.
@@ -214,16 +195,16 @@ Pattern::process(const String &subject, StringVector &result)
214195bool
215196Pattern::match (const String &subject)
216197{
217- int matchCount;
218198 AccessControlDebug (" matching '%s' to '%s'" , _pattern.c_str (), subject.c_str ());
219199
220- if (!_re) {
200+ if (!_re || _re-> empty () ) {
221201 return false ;
222202 }
223203
224- matchCount = pcre_exec (_re, _extra, subject.c_str (), subject.length (), 0 , PCRE_NOTEMPTY, nullptr , 0 );
204+ RegexMatches matches (TOKENCOUNT);
205+ int matchCount = _re->exec (subject, matches, RE_NOTEMPTY);
225206 if (matchCount < 0 ) {
226- if (matchCount != PCRE_ERROR_NOMATCH ) {
207+ if (matchCount != RE_ERROR_NOMATCH ) {
227208 AccessControlError (" matching error %d" , matchCount);
228209 }
229210 return false ;
@@ -240,31 +221,27 @@ Pattern::match(const String &subject)
240221bool
241222Pattern::capture (const String &subject, StringVector &result)
242223{
243- int matchCount;
244- int ovector[OVECOUNT];
245-
246224 AccessControlDebug (" capturing '%s' from '%s'" , _pattern.c_str (), subject.c_str ());
247225
248- if (!_re) {
226+ if (!_re || _re-> empty () ) {
249227 AccessControlError (" regular expression not initialized" );
250228 return false ;
251229 }
252230
253- matchCount = pcre_exec (_re, nullptr , subject.c_str (), subject.length (), 0 , PCRE_NOTEMPTY, ovector, OVECOUNT);
231+ RegexMatches matches (TOKENCOUNT);
232+ int matchCount = _re->exec (subject, matches, RE_NOTEMPTY);
254233 if (matchCount < 0 ) {
255- if (matchCount != PCRE_ERROR_NOMATCH ) {
234+ if (matchCount != RE_ERROR_NOMATCH ) {
256235 AccessControlError (" matching error %d" , matchCount);
257236 }
258237 return false ;
259238 }
260239
261240 for (int i = 0 ; i < matchCount; i++) {
262- int start = ovector[ 2 * i];
263- int length = ovector[ 2 * i + 1 ] - ovector[ 2 * i] ;
241+ std::string_view match_view = matches[ i];
242+ String dst (match_view. data (), match_view. size ()) ;
264243
265- String dst (subject, start, length);
266-
267- AccessControlDebug (" capturing '%s' %d[%d,%d]" , dst.c_str (), i, ovector[2 * i], ovector[2 * i + 1 ]);
244+ AccessControlDebug (" capturing '%s' %d" , dst.c_str (), i);
268245 result.push_back (dst);
269246 }
270247
@@ -280,19 +257,17 @@ Pattern::capture(const String &subject, StringVector &result)
280257bool
281258Pattern::replace (const String &subject, String &result)
282259{
283- int matchCount;
284- int ovector[OVECOUNT];
285-
286260 AccessControlDebug (" replacing:'%s' in pattern:'%s', subject:'%s'" , _replacement.c_str (), _pattern.c_str (), subject.c_str ());
287261
288- if (!_re || !_replace) {
262+ if (!_re || _re-> empty () || !_replace) {
289263 AccessControlError (" regular expression not initialized or not configured to replace" );
290264 return false ;
291265 }
292266
293- matchCount = pcre_exec (_re, nullptr , subject.c_str (), subject.length (), 0 , PCRE_NOTEMPTY, ovector, OVECOUNT);
267+ RegexMatches matches (TOKENCOUNT);
268+ int matchCount = _re->exec (subject, matches, RE_NOTEMPTY);
294269 if (matchCount < 0 ) {
295- if (matchCount != PCRE_ERROR_NOMATCH ) {
270+ if (matchCount != RE_ERROR_NOMATCH ) {
296271 AccessControlError (" matching error %d" , matchCount);
297272 }
298273 return false ;
@@ -308,12 +283,11 @@ Pattern::replace(const String &subject, String &result)
308283
309284 int previous = 0 ;
310285 for (int i = 0 ; i < _tokenCount; i++) {
311- int replIndex = _tokens[i];
312- int start = ovector[2 * replIndex];
313- int length = ovector[2 * replIndex + 1 ] - ovector[2 * replIndex];
286+ int replIndex = _tokens[i];
287+ std::string_view match_view = matches[replIndex];
314288
315289 String src (_replacement, _tokenOffset[i], 2 );
316- String dst (subject, start, length );
290+ String dst (match_view. data (), match_view. size () );
317291
318292 AccessControlDebug (" replacing '%s' with '%s'" , src.c_str (), dst.c_str ());
319293
@@ -337,31 +311,16 @@ Pattern::replace(const String &subject, String &result)
337311bool
338312Pattern::compile ()
339313{
340- const char *errPtr ; /* PCRE error */
314+ std::string error ; /* PCRE error description */
341315 int errOffset; /* PCRE error offset */
342316
343317 AccessControlDebug (" compiling pattern:'%s', replace: %s, replacement:'%s'" , _pattern.c_str (), _replace ? " true" : " false" ,
344318 _replacement.c_str ());
345319
346- _re = pcre_compile (_pattern.c_str (), /* the pattern */
347- 0 , /* options */
348- &errPtr, /* for error message */
349- &errOffset, /* for error offset */
350- nullptr ); /* use default character tables */
351-
352- if (nullptr == _re) {
353- AccessControlError (" compile of regex '%s' at char %d: %s" , _pattern.c_str (), errOffset, errPtr);
354-
355- return false ;
356- }
357-
358- _extra = pcre_study (_re, 0 , &errPtr);
359-
360- if ((nullptr == _extra) && (nullptr != errPtr) && (0 != *errPtr)) {
361- AccessControlError (" failed to study regex '%s': %s" , _pattern.c_str (), errPtr);
362-
363- pcre_free (_re);
364- _re = nullptr ;
320+ _re = std::make_unique<Regex>();
321+ if (!_re->compile (_pattern, error, errOffset, 0 )) {
322+ AccessControlError (" compile of regex '%s' at char %d: %s" , _pattern.c_str (), errOffset, error.c_str ());
323+ _re.reset ();
365324 return false ;
366325 }
367326
@@ -398,7 +357,7 @@ Pattern::compile()
398357 }
399358
400359 if (!success) {
401- pcreFree ();
360+ _re. reset ();
402361 }
403362
404363 return success;
0 commit comments