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,22 +195,13 @@ 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) {
221- return false ;
222- }
223-
224- matchCount = pcre_exec (_re, _extra, subject.c_str (), subject.length (), 0 , PCRE_NOTEMPTY, nullptr , 0 );
225- if (matchCount < 0 ) {
226- if (matchCount != PCRE_ERROR_NOMATCH) {
227- AccessControlError (" matching error %d" , matchCount);
228- }
200+ if (!_re || _re->empty ()) {
229201 return false ;
230202 }
231203
232- return true ;
204+ return _re-> exec (subject, RE_NOTEMPTY) ;
233205}
234206
235207/* *
@@ -240,31 +212,24 @@ Pattern::match(const String &subject)
240212bool
241213Pattern::capture (const String &subject, StringVector &result)
242214{
243- int matchCount;
244- int ovector[OVECOUNT];
245-
246215 AccessControlDebug (" capturing '%s' from '%s'" , _pattern.c_str (), subject.c_str ());
247216
248- if (!_re) {
217+ if (!_re || _re-> empty () ) {
249218 AccessControlError (" regular expression not initialized" );
250219 return false ;
251220 }
252221
253- matchCount = pcre_exec (_re, nullptr , subject.c_str (), subject.length (), 0 , PCRE_NOTEMPTY, ovector, OVECOUNT);
222+ RegexMatches matches (TOKENCOUNT);
223+ int matchCount = _re->exec (subject, matches, RE_NOTEMPTY);
254224 if (matchCount < 0 ) {
255- if (matchCount != PCRE_ERROR_NOMATCH) {
256- AccessControlError (" matching error %d" , matchCount);
257- }
258225 return false ;
259226 }
260227
261228 for (int i = 0 ; i < matchCount; i++) {
262- int start = ovector[ 2 * i];
263- int length = ovector[ 2 * i + 1 ] - ovector[ 2 * i] ;
229+ std::string_view match_view = matches[ i];
230+ String dst (match_view. data (), match_view. size ()) ;
264231
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 ]);
232+ AccessControlDebug (" capturing '%s' %d" , dst.c_str (), i);
268233 result.push_back (dst);
269234 }
270235
@@ -280,21 +245,16 @@ Pattern::capture(const String &subject, StringVector &result)
280245bool
281246Pattern::replace (const String &subject, String &result)
282247{
283- int matchCount;
284- int ovector[OVECOUNT];
285-
286248 AccessControlDebug (" replacing:'%s' in pattern:'%s', subject:'%s'" , _replacement.c_str (), _pattern.c_str (), subject.c_str ());
287249
288- if (!_re || !_replace) {
250+ if (!_re || _re-> empty () || !_replace) {
289251 AccessControlError (" regular expression not initialized or not configured to replace" );
290252 return false ;
291253 }
292254
293- matchCount = pcre_exec (_re, nullptr , subject.c_str (), subject.length (), 0 , PCRE_NOTEMPTY, ovector, OVECOUNT);
255+ RegexMatches matches (TOKENCOUNT);
256+ int matchCount = _re->exec (subject, matches, RE_NOTEMPTY);
294257 if (matchCount < 0 ) {
295- if (matchCount != PCRE_ERROR_NOMATCH) {
296- AccessControlError (" matching error %d" , matchCount);
297- }
298258 return false ;
299259 }
300260
@@ -308,12 +268,11 @@ Pattern::replace(const String &subject, String &result)
308268
309269 int previous = 0 ;
310270 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];
271+ int replIndex = _tokens[i];
272+ std::string_view match_view = matches[replIndex];
314273
315274 String src (_replacement, _tokenOffset[i], 2 );
316- String dst (subject, start, length );
275+ String dst (match_view. data (), match_view. size () );
317276
318277 AccessControlDebug (" replacing '%s' with '%s'" , src.c_str (), dst.c_str ());
319278
@@ -337,31 +296,16 @@ Pattern::replace(const String &subject, String &result)
337296bool
338297Pattern::compile ()
339298{
340- const char *errPtr ; /* PCRE error */
299+ std::string error ; /* PCRE error description */
341300 int errOffset; /* PCRE error offset */
342301
343302 AccessControlDebug (" compiling pattern:'%s', replace: %s, replacement:'%s'" , _pattern.c_str (), _replace ? " true" : " false" ,
344303 _replacement.c_str ());
345304
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 ;
305+ _re = std::make_unique<Regex>();
306+ if (!_re->compile (_pattern, error, errOffset, 0 )) {
307+ AccessControlError (" compile of regex '%s' at char %d: %s" , _pattern.c_str (), errOffset, error.c_str ());
308+ _re.reset ();
365309 return false ;
366310 }
367311
@@ -398,7 +342,7 @@ Pattern::compile()
398342 }
399343
400344 if (!success) {
401- pcreFree ();
345+ _re. reset ();
402346 }
403347
404348 return success;
0 commit comments