1818
1919/* *
2020 * @file pattern.cc
21- * @brief PRCE related classes.
21+ * @brief Regex related classes.
2222 * @see pattern.h
2323 */
2424
@@ -41,16 +41,14 @@ replaceString(String &str, const String &from, const String &to)
4141Pattern::Pattern () : _pattern(" " ), _replacement(" " ) {}
4242
4343/* *
44- * @brief Initializes PCRE pattern by providing the subject and replacement strings.
45- * @param pattern PCRE pattern, a string containing PCRE patterns, capturing groups.
46- * @param replacement PCRE replacement, a string where $0 ... $9 will be replaced with the corresponding capturing groups
44+ * @brief Initializes Regex pattern by providing the subject and replacement strings.
45+ * @param pattern Regex pattern, a string containing regex patterns, capturing groups.
46+ * @param replacement Regex replacement, a string where $0 ... $9 will be replaced with the corresponding capturing groups
4747 * @return true if successful, false if failure
4848 */
4949bool
5050Pattern::init (const String &pattern, const String &replacement, bool replace)
5151{
52- pcreFree ();
53-
5452 _pattern.assign (pattern);
5553 _replacement.assign (replacement);
5654 _replace = replace;
@@ -59,17 +57,16 @@ Pattern::init(const String &pattern, const String &replacement, bool replace)
5957
6058 if (!compile ()) {
6159 CacheKeyDebug (" failed to initialize pattern:'%s', replacement:'%s'" , pattern.c_str (), replacement.c_str ());
62- pcreFree ();
6360 return false ;
6461 }
6562
6663 return true ;
6764}
6865
6966/* *
70- * @brief Initializes PCRE pattern by providing the pattern only or pattern+replacement in a single configuration string.
67+ * @brief Initializes Regex pattern by providing the pattern only or pattern+replacement in a single configuration string.
7168 * @see init()
72- * @param config PCRE pattern <pattern> or PCRE pattern + replacement in format /<pattern>/<replacement>/
69+ * @param config Regex pattern <pattern> or Regex pattern + replacement in format /<pattern>/<replacement>/
7370 * @return true if successful, false if failure
7471 */
7572bool
@@ -130,32 +127,7 @@ Pattern::init(const String &config)
130127bool
131128Pattern::empty () const
132129{
133- return _pattern.empty () || nullptr == _re;
134- }
135-
136- /* *
137- * @brief Frees PCRE library related resources.
138- */
139- void
140- Pattern::pcreFree ()
141- {
142- if (_re) {
143- pcre_free (_re);
144- _re = nullptr ;
145- }
146-
147- if (_extra) {
148- pcre_free (_extra);
149- _extra = nullptr ;
150- }
151- }
152-
153- /* *
154- * @brief Destructor, frees PCRE related resources.
155- */
156- Pattern::~Pattern ()
157- {
158- pcreFree ();
130+ return _pattern.empty () || _re.empty ();
159131}
160132
161133/* *
@@ -198,23 +170,23 @@ Pattern::process(const String &subject, StringVector &result)
198170}
199171
200172/* *
201- * @brief PCRE matches a subject string against the regex pattern.
202- * @param subject PCRE subject
173+ * @brief Regex matches a subject string against the regex pattern.
174+ * @param subject Regex subject
203175 * @return true - matched, false - did not.
204176 */
205177bool
206178Pattern::match (const String &subject)
207179{
208- int matchCount;
209180 CacheKeyDebug (" matching '%s' to '%s'" , _pattern.c_str (), subject.c_str ());
210181
211- if (! _re) {
182+ if (_re. empty () ) {
212183 return false ;
213184 }
214185
215- matchCount = pcre_exec (_re, _extra, subject.c_str (), subject.length (), 0 , PCRE_NOTEMPTY, nullptr , 0 );
186+ RegexMatches matches;
187+ int matchCount = _re.exec (subject, matches, RE_NOTEMPTY);
216188 if (matchCount < 0 ) {
217- if (matchCount != PCRE_ERROR_NOMATCH ) {
189+ if (matchCount != RE_ERROR_NOMATCH ) {
218190 CacheKeyError (" matching error %d" , matchCount);
219191 }
220192 return false ;
@@ -224,66 +196,60 @@ Pattern::match(const String &subject)
224196}
225197
226198/* *
227- * @brief Return all PCRE capture groups that matched in the subject string
228- * @param subject PCRE subject string
199+ * @brief Return all Regex capture groups that matched in the subject string
200+ * @param subject Regex subject string
229201 * @param result reference to vector of strings containing all capture groups
230202 */
231203bool
232204Pattern::capture (const String &subject, StringVector &result)
233205{
234- int matchCount;
235- int ovector[OVECOUNT];
236-
237206 CacheKeyDebug (" capturing '%s' from '%s'" , _pattern.c_str (), subject.c_str ());
238207
239- if (! _re) {
208+ if (_re. empty () ) {
240209 CacheKeyError (" regular expression not initialized" );
241210 return false ;
242211 }
243212
244- matchCount = pcre_exec (_re, nullptr , subject.c_str (), subject.length (), 0 , PCRE_NOTEMPTY, ovector, OVECOUNT);
213+ RegexMatches matches;
214+ int matchCount = _re.exec (subject, matches, RE_NOTEMPTY);
245215 if (matchCount < 0 ) {
246- if (matchCount != PCRE_ERROR_NOMATCH ) {
216+ if (matchCount != RE_ERROR_NOMATCH ) {
247217 CacheKeyError (" matching error %d" , matchCount);
248218 }
249219 return false ;
250220 }
251221
252222 for (int i = 0 ; i < matchCount; i++) {
253- int start = ovector[ 2 * i];
254- int length = ovector[ 2 * i + 1 ] - ovector[ 2 * i] ;
223+ std::string_view capture = matches[ i];
224+ String dst (capture. data (), capture. length ()) ;
255225
256- String dst (subject, start, length);
257-
258- CacheKeyDebug (" capturing '%s' %d[%d,%d]" , dst.c_str (), i, ovector[2 * i], ovector[2 * i + 1 ]);
226+ CacheKeyDebug (" capturing '%s' %d" , dst.c_str (), i);
259227 result.push_back (dst);
260228 }
261229
262230 return true ;
263231}
264232
265233/* *
266- * @brief Replaces all replacements found in the replacement string with what matched in the PCRE capturing groups.
267- * @param subject PCRE subject string
234+ * @brief Replaces all replacements found in the replacement string with what matched in the Regex capturing groups.
235+ * @param subject Regex subject string
268236 * @param result reference to A string where the result of the replacement will be stored
269237 * @return true - success, false - nothing matched or failure.
270238 */
271239bool
272240Pattern::replace (const String &subject, String &result)
273241{
274- int matchCount;
275- int ovector[OVECOUNT];
276-
277242 CacheKeyDebug (" replacing:'%s' in pattern:'%s', subject:'%s'" , _replacement.c_str (), _pattern.c_str (), subject.c_str ());
278243
279- if (! _re || !_replace) {
244+ if (_re. empty () || !_replace) {
280245 CacheKeyError (" regular expression not initialized or not configured to replace" );
281246 return false ;
282247 }
283248
284- matchCount = pcre_exec (_re, nullptr , subject.c_str (), subject.length (), 0 , PCRE_NOTEMPTY, ovector, OVECOUNT);
249+ RegexMatches matches;
250+ int matchCount = _re.exec (subject, matches, RE_NOTEMPTY);
285251 if (matchCount < 0 ) {
286- if (matchCount != PCRE_ERROR_NOMATCH ) {
252+ if (matchCount != RE_ERROR_NOMATCH ) {
287253 CacheKeyError (" matching error %d" , matchCount);
288254 }
289255 return false ;
@@ -299,18 +265,11 @@ Pattern::replace(const String &subject, String &result)
299265
300266 int previous = 0 ;
301267 for (int i = 0 ; i < _tokenCount; i++) {
302- int replIndex = _tokens[i];
303- int start = ovector[2 * replIndex];
304- int length = ovector[2 * replIndex + 1 ] - ovector[2 * replIndex];
305-
306- /* Handle the case when no match / a group capture result in an empty string */
307- if (start < 0 ) {
308- start = 0 ;
309- length = 0 ;
310- }
268+ int replIndex = _tokens[i];
269+ std::string_view capture = matches[replIndex];
311270
312271 String src (_replacement, _tokenOffset[i], 2 );
313- String dst (subject, start, length);
272+ String dst (capture. data (), capture. length () );
314273
315274 CacheKeyDebug (" replacing '%s' with '%s'" , src.c_str (), dst.c_str ());
316275
@@ -328,37 +287,20 @@ Pattern::replace(const String &subject, String &result)
328287}
329288
330289/* *
331- * @brief PCRE compiles the regex, called only during initialization.
290+ * @brief Compiles the regex, called only during initialization.
332291 * @return true if successful, false if not.
333292 */
334293bool
335294Pattern::compile ()
336295{
337- const char *errPtr; /* PCRE error */
338- int errOffset; /* PCRE error offset */
296+ std::string error;
297+ int errOffset;
339298
340299 CacheKeyDebug (" compiling pattern:'%s', replace: %s, replacement:'%s'" , _pattern.c_str (), _replace ? " true" : " false" ,
341300 _replacement.c_str ());
342301
343- _re = pcre_compile (_pattern.c_str (), /* the pattern */
344- 0 , /* options */
345- &errPtr, /* for error message */
346- &errOffset, /* for error offset */
347- nullptr ); /* use default character tables */
348-
349- if (nullptr == _re) {
350- CacheKeyError (" compile of regex '%s' at char %d: %s" , _pattern.c_str (), errOffset, errPtr);
351-
352- return false ;
353- }
354-
355- _extra = pcre_study (_re, 0 , &errPtr);
356-
357- if ((nullptr == _extra) && (nullptr != errPtr) && (0 != *errPtr)) {
358- CacheKeyError (" failed to study regex '%s': %s" , _pattern.c_str (), errPtr);
359-
360- pcre_free (_re);
361- _re = nullptr ;
302+ if (!_re.compile (_pattern, error, errOffset)) {
303+ CacheKeyError (" compile of regex '%s' at char %d: %s" , _pattern.c_str (), errOffset, error.c_str ());
362304 return false ;
363305 }
364306
@@ -394,10 +336,6 @@ Pattern::compile()
394336 }
395337 }
396338
397- if (!success) {
398- pcreFree ();
399- }
400-
401339 return success;
402340}
403341
0 commit comments