BDE 4.39.x Production Release
Loading...
Searching...
No Matches
bdlpcre_regex.h
Go to the documentation of this file.
1/// @file bdlpcre_regex.h
2///
3/// The content of this file has been pre-processed for Doxygen.
4///
5
6
7// bdlpcre_regex.h -*-C++-*-
8#ifndef INCLUDED_BDLPCRE_REGEX
9#define INCLUDED_BDLPCRE_REGEX
10
11#include <bsls_ident.h>
12BSLS_IDENT("$Id$ $CSID$")
13
14/// @defgroup bdlpcre_regex bdlpcre_regex
15/// @brief Provide a mechanism for regular expression pattern matching.
16/// @addtogroup bdl
17/// @{
18/// @addtogroup bdlpcre
19/// @{
20/// @addtogroup bdlpcre_regex
21/// @{
22///
23/// <h1> Outline </h1>
24/// * <a href="#bdlpcre_regex-purpose"> Purpose</a>
25/// * <a href="#bdlpcre_regex-classes"> Classes </a>
26/// * <a href="#bdlpcre_regex-description"> Description </a>
27/// * <a href="#bdlpcre_regex-prepared-state"> "Prepared" State </a>
28/// * <a href="#bdlpcre_regex-prepare-time-flags"> Prepare-Time Flags </a>
29/// * <a href="#bdlpcre_regex-case-insensitive-matching"> Case-Insensitive Matching </a>
30/// * <a href="#bdlpcre_regex-multi-line-matching"> Multi-Line Matching </a>
31/// * <a href="#bdlpcre_regex-utf-8-support"> UTF-8 Support </a>
32/// * <a href="#bdlpcre_regex-dot-matches-all"> Dot Matches All </a>
33/// * <a href="#bdlpcre_regex-allow-duplicate-named-groups"> Allow Duplicate Named Groups (sub-patterns) </a>
34/// * <a href="#bdlpcre_regex-creating-a-new-string-with-replacement"> Creating a New String with Replacement </a>
35/// * <a href="#bdlpcre_regex-group-insertion-forms"> Group Insertion Forms </a>
36/// * <a href="#bdlpcre_regex-replacement-flags"> Replacement Flags </a>
37/// * <a href="#bdlpcre_regex-global-replacement"> Global Replacement </a>
38/// * <a href="#bdlpcre_regex-the-replacement-string-is-literal"> The Replacement String is Literal </a>
39/// * <a href="#bdlpcre_regex-extended-replacement-processing"> Extended Replacement Processing </a>
40/// * <a href="#bdlpcre_regex-treat-unknown-group-as-unset"> Treat Unknown Group As Unset </a>
41/// * <a href="#bdlpcre_regex-insert-an-empty-string-for-unset-group"> Insert An Empty String For Unset Group </a>
42/// * <a href="#bdlpcre_regex-jit-compiling-optimization"> JIT Compiling Optimization </a>
43/// * <a href="#bdlpcre_regex-thread-safety"> Thread Safety </a>
44/// * <a href="#bdlpcre_regex-note-on-memory-allocation-exceptions"> Note on Memory Allocation Exceptions </a>
45/// * <a href="#bdlpcre_regex-usage"> Usage </a>
46/// * <a href="#bdlpcre_regex-appendix-perl-compatibility"> Appendix: Perl Compatibility </a>
47/// * <a href="#bdlpcre_regex-additional-copyright-notice"> Additional Copyright Notice </a>
48///
49/// # Purpose {#bdlpcre_regex-purpose}
50/// Provide a mechanism for regular expression pattern matching.
51///
52/// # Classes {#bdlpcre_regex-classes}
53///
54/// - bdlpcre::RegEx: mechanism for compiling and matching regular expressions
55///
56/// @see http://www.pcre.org/
57///
58/// # Description {#bdlpcre_regex-description}
59/// This component provides a mechanism, `bdlpcre::RegEx`, for
60/// compiling (or "preparing") regular expressions, and subsequently matching
61/// subject strings against a prepared expression and replacing the matching
62/// parts with the replacement string. The regular expressions supported by
63/// this component correspond approximately with Perl 5.10. See the appendix
64/// entitled "Perl Compatibility" below for more information.
65///
66/// Upon construction, a `bdlpcre::RegEx` object is initially not associated
67/// with a regular expression. A regular expression pattern is compiled for use
68/// by the object using the `prepare` method. Subject strings may then be
69/// matched against the prepared pattern using the set of overloaded `match`
70/// methods.
71///
72/// The component provides the following groups of `match` overloads (and
73/// similarly for `matchRaw`):
74///
75/// 1. The first group of `match` overloads simply returns 0 if a given subject
76/// string matches the prepared regular expression, and returns a non-zero
77/// value otherwise.
78/// 2. The second group of `match` overloads returns the substring of the
79/// subject that was matched, either as a `bsl::string_view`, or as a
80/// `bsl::pair<size_t, size_t>` holding the (offset, length) pair.
81/// 3. The third group of `match` overloads returns a vector of either
82/// `bsl::string_view` or `bsl::pair<size_t, size_t>` holding the matched
83/// substrings. The first element of the vector indicate the substring of
84/// the subject that matched the entire pattern. Subsequent elements
85/// indicate the substrings of the subject that matched respective
86/// sub-patterns.
87///
88/// The matched parts of subjects strings can be replaced with the replacement
89/// string using the set of overloaded `replace` and `replaceRaw` methods.
90///
91/// ## "Prepared" State {#bdlpcre_regex-prepared-state}
92///
93///
94/// A `bdlpcre::RegEx` object must first be prepared with a valid regular
95/// expression before attempting to match subject strings or replace the matched
96/// parts. We say that an instance of `bdlpcre::RegEx` is in the "prepared"
97/// state if the object holds a valid regular expression, in which case calls to
98/// the overloaded `match` or `replace` methods of that instance are valid.
99/// Otherwise, the object is in the "unprepared" state. Upon construction, an
100/// `bdlpcre::RegEx` object is in the "unprepared" state. A successful call to
101/// the `prepare` method puts the object into the "prepared" state. The `clear`
102/// method, as well as an unsuccessful call to `prepare`, puts the object into
103/// the "unprepared" state. The `isPrepared` accessor may be used to determine
104/// whether an object is prepared.
105///
106/// ## Prepare-Time Flags {#bdlpcre_regex-prepare-time-flags}
107///
108///
109/// A set of flags may be optionally supplied to the `prepare` method to affect
110/// specific pattern matching behavior. The flags recognized by `prepare` are
111/// defined in an enumeration declared within the `bdlpcre::RegEx`. The
112/// following describes these flags and their effects.
113///
114/// ### Case-Insensitive Matching {#bdlpcre_regex-case-insensitive-matching}
115///
116///
117/// If `RegEx::k_FLAG_CASELESS` is included in the flags supplied to `prepare`,
118/// then letters in the regular expression pattern supplied to `prepare` match
119/// both lower- and upper-case letters in subject strings subsequently supplied
120/// to `match`. This is equivalent to Perl's `/i` option, and can be turned off
121/// within a pattern by a `(?i)` option setting.
122///
123/// ### Multi-Line Matching {#bdlpcre_regex-multi-line-matching}
124///
125///
126/// By default, a subject string supplied to `match` or `replace` is treated as
127/// consisting of a single line of characters (even if it actually contains `\n`
128/// characters). The start-of-line meta-character `^` matches only at the
129/// beginning of the string, and the end-of-line meta-character `$` matches only
130/// at the end of the string (or before a terminating `\n`, if present). This
131/// matches the behavior of Perl.
132///
133/// If `RegEx::k_FLAG_MULTILINE` is included in the flags supplied to `prepare`,
134/// then start-of-line and end-of-line meta-characters match immediately
135/// following or immediately before any `\n` characters in subject strings
136/// supplied to `match`, respectively (as well as at the very start and end of
137/// subject strings). This is equivalent to Perl's `/m` option, and can be
138/// turned off within a pattern by a `(?m)` option setting. If there are no
139/// `\n` characters in the subject string, or if there are no occurrences of `^`
140/// or `$` in the prepared pattern, then including `k_FLAG_MULTILINE` has no
141/// effect.
142///
143/// ### UTF-8 Support {#bdlpcre_regex-utf-8-support}
144///
145///
146/// If `RegEx::k_FLAG_UTF8` is included in the flags supplied to `prepare`, then
147/// the regular expression pattern supplied to `prepare`, the subject strings
148/// subsequently supplied to `match`, `matchRaw`, `replace`, and `replaceRaw` as
149/// well as the replacement string supplied to `replace` and `replaceRaw` are
150/// interpreted as strings of UTF-8 characters instead of strings of ASCII
151/// characters. `match` and `replace` return a non-zero value if `pattern()`
152/// was prepared with `k_FLAG_UTF8`, but the subject or the replacement are not
153/// a valid UTF-8 string. The behavior of `matchRaw` is undefined if
154/// `pattern()` was prepared with `k_FLAG_UTF8`, but the subject is not a valid
155/// UTF-8 string. Note that JIT optimization (see below) is disabled for
156/// `match` if `pattern()` was prepared with `k_FLAG_UTF8`.
157///
158/// ### Dot Matches All {#bdlpcre_regex-dot-matches-all}
159///
160///
161/// If `RegEx::k_FLAG_DOTMATCHESALL` is included in the flags supplied to
162/// `prepare`, then a dot metacharacter in the pattern matches a character of
163/// any value, including one that indicates a newline. However, it only ever
164/// matches one character, even if newlines are encoded as `\r\n`. If
165/// `k_FLAG_DOTMATCHESALL` is not used to prepare a regular expression, a dot
166/// metacharacter will *not* match a newline; hence, patterns expected to match
167/// across lines will fail to do so. This flag is equivalent to Perl's `/s`
168/// option, and can be changed within a pattern by a `(?s)` option setting. A
169/// negative class such as `[^a]` always matches newline characters, independent
170/// of the setting of this option.
171///
172/// ### Allow Duplicate Named Groups (sub-patterns) {#bdlpcre_regex-allow-duplicate-named-groups}
173///
174///
175/// If `RegEx::k_FLAG_DUPNAMES` is included in the flags supplied to `prepare`,
176/// then sub-pattern names can be used more than once. Alternatively this
177/// feature can be turned on within a pattern by a `(?J)` option setting
178/// (see https://www.pcre.org/current/doc/html/pcre2syntax.html#SEC16). The
179/// `subpatternIndex(name)` call will fail if `name` is used more than once - in
180/// that case, the `namedSubpatterns()` call should be used.
181/// `namedSubpatterns()` returns a set of (name, index) pairs used in the
182/// pattern.
183///
184/// ## Creating a New String with Replacement {#bdlpcre_regex-creating-a-new-string-with-replacement}
185///
186///
187/// A new string can be created by applying the regular expression pattern to
188/// the subject string in which the matching parts are replaced with the
189/// replacement string supplied to the `replace` and `replaceRaw` methods.
190///
191/// ### Group Insertion Forms {#bdlpcre_regex-group-insertion-forms}
192///
193///
194/// By default, a dollar character (`$`) is an escape character that can specify
195/// the insertion of characters from capture groups and names from `(*MARK)` or
196/// other control verbs in the pattern (see
197/// https://perldoc.perl.org/perlre#Special-Backtracking-Control-Verbs for
198/// details). The following forms are always recognized:
199/// @code
200/// $$ insert a dollar character
201/// $<n> or ${<n>} insert the contents of group <n>
202/// $*MARK or ${*MARK} insert a control verb name
203/// @endcode
204/// Either a group number or a group name can be given for `<n>`. Curly braces
205/// are required only if the following character would be interpreted as part of
206/// the number or name. The number may be zero to include the entire matched
207/// string. For example, if the pattern `a(b)c` is matched with `=abc=` and the
208/// replacement string `+$1$0$1+`, the result is `=+babcb+=`.
209///
210/// ### Replacement Flags {#bdlpcre_regex-replacement-flags}
211///
212///
213/// A set of flags may be optionally supplied to the `replace` and `replaceRaw`
214/// method to affect specific substitution behavior. The flags recognized by
215/// `replace` and `replaceRaw` are defined in an enumeration declared within the
216/// `bdlpcre::RegEx`. The flags are passed as a bitwise combination of OR bits
217/// in the `options` argument to `replace` and `replaceRaw` (e.g.,
218/// 'k_REPLACE_GLOBAL | k_REPLACE_LITERAL). The flags reflect
219/// `PCRE_SUBSTITUTE_*` flags and are propagated to the underlying PCRE2 library
220/// substitute function. See
221/// {https://www.pcre.org/current/doc/html/pcre2api.html#SEC36} for details. The
222/// following describes these flags and their effects.
223///
224/// #### Global Replacement {#bdlpcre_regex-global-replacement}
225///
226///
227/// The default action of `replace` and `replaceRaw` is to perform just one
228/// replacement if the pattern matches. The `RegEx::k_REPLACE_GLOBAL` flag
229/// requests multiple replacements in the subject string.
230///
231/// ### The Replacement String is Literal {#bdlpcre_regex-the-replacement-string-is-literal}
232///
233///
234/// If `RegEx::k_REPLACE_LITERAL` is set, the replacement string is not
235/// interpreted in any way.
236///
237/// #### Extended Replacement Processing {#bdlpcre_regex-extended-replacement-processing}
238///
239///
240/// If `RegEx::k_REPLACE_EXTENDED` is set, extra processing is applied to the
241/// replacement string. Without this option, only the dollar character (`$`) is
242/// special, and only the group insertion forms listed above (see
243/// {Group Insertion Forms}) are valid. When this flag is set, two things
244/// change:
245///
246/// * Firstly, backslash in a replacement string is interpreted as an escape
247/// character. The usual forms such as `\n` or `\x{ddd}` can be used to
248/// specify particular character codes, and backslash followed by any
249/// non-alphanumeric character quotes that character. Extended quoting can
250/// be coded using `\Q...\E`, exactly as in the pattern string.
251/// * The second effect is to add more flexibility to capture group
252/// substitution. The syntax is similar to that used by Bash:
253/// ```
254/// ${<n>:-<string>}
255/// ${<n>:+<string1>:<string2>}
256/// ```
257/// As before, `<n>` may be a group number or a name. The first form
258/// specifies a default value. If group `<n>` is set, its value is inserted;
259/// if not, `<string>` is expanded and the result inserted. The second form
260/// specifies strings that are expanded and inserted when group `<n>` is set
261/// or unset, respectively. The first form is just a convenient shorthand
262/// for `${<n>:+${<n>}:<string>}`.
263///
264/// #### Treat Unknown Group As Unset {#bdlpcre_regex-treat-unknown-group-as-unset}
265///
266///
267/// The `RegEx::k_REPLACE_UNKNOWN_UNSET` causes references to capture groups
268/// that do not appear in the pattern to be treated as unset groups.
269///
270/// #### Insert An Empty String For Unset Group {#bdlpcre_regex-insert-an-empty-string-for-unset-group}
271///
272///
273/// The `RegEx::k_REPLACE_UNSET_EMPTY` causes unset capture groups (including
274/// unknown groups when `RegEx::k_REPLACE_UNKNOWN_UNSET` is set) to be treated
275/// as empty strings when inserted as described in {Group Insertion Forms}. If
276/// this option is not set, an attempt to insert an unset group causes `replace`
277/// and `replaceRaw` to return an error. This option does not influence the
278/// extended substitution syntax described in {Extended Replacement Processing}.
279///
280/// ## JIT Compiling Optimization {#bdlpcre_regex-jit-compiling-optimization}
281///
282///
283/// Just-in-time compiling is a heavyweight optimization that can greatly speed
284/// up pattern matching on supported platforms. However, it comes at the cost
285/// of extra processing before the match is performed, so it is of most benefit
286/// when the same pattern is going to be matched many times. This does not
287/// necessarily mean many calls of a matching function; if the pattern is not
288/// anchored, matching attempts may take place many times at various positions
289/// in the subject, even for a single call. Therefore, if the subject string is
290/// very long, it may still pay to use JIT even for one-off matches.
291///
292/// If `RegEx::k_FLAG_JIT` is included in the flags supplied to `prepare`, then
293/// all following matches performed by `matchRaw` will be JIT optimized.
294/// Matches performed by `match` will also be JIT optimized provided that
295/// `RegEx::k_FLAG_UTF8` was not supplied to `prepare` (since UTF-8 string
296/// validity checking is not done during JIT compilation). To disable JIT
297/// optimization for all matches, prepare the regular expression again omitting
298/// the `k_FLAG_JIT` flag.
299///
300/// JIT is supported on the following platforms:
301/// @code
302/// ARM 32-bit (v5, v7, and Thumb2)
303/// ARM 64-bit
304/// Intel x86 32-bit and 64-bit
305/// MIPS 32-bit and 64-bit
306/// Power PC 32-bit and 64-bit
307/// SPARC 32-bit
308/// @endcode
309///
310/// The tables below demonstrate the benefit of the `match` method with JIT
311/// optimizations, as well as the increased cost for `prepare` when enabling JIT
312/// optimizations:
313/// @code
314/// Legend
315/// ------
316/// 'SIMPLE_PATTERN':
317/// Pattern - X(abc)*Z
318/// Subject - XXXabcabcZZZ
319///
320/// 'EMAIL_PATTERN':
321/// Pattern - [A-Za-z0-9._-]+@[[A-Za-z0-9.-]+
322/// Subject - john.dow@bloomberg.net
323///
324/// 'IP_ADDRESS_PATTERN':
325/// Pattern - (?:[0-9]{1,3}\.){3}[0-9]{1,3}
326/// Subject - 255.255.255.255
327///
328/// Each pattern/subject returns 1 match.
329/// @endcode
330/// In this first table, for each pattern, `prepare` was called once, and match
331/// was called 100000 times (measurements are in seconds):
332/// @code
333/// Table 1: Performance Improvement for 'match' using k_JIT_FLAG
334/// +--------------------+---------------------+---------------------+
335/// | Pattern | 'match' without-JIT | 'match' using-JIT |
336/// +====================+=====================+=====================+
337/// | SIMPLE_PATTERN | 0.0559 (~5.1x) | 0.0108 |
338/// +--------------------+---------------------+---------------------+
339/// | EMAIL_PATTERN | 0.0222 (~2.6x) | 0.0086 |
340/// +--------------------+---------------------+---------------------+
341/// | IP_ADDRESS_PATTERN | 0.0331 (~5.3x) | 0.0062 |
342/// +--------------------+---------------------+---------------------+
343/// @endcode
344/// In this second table, for each pattern, we measured 10000 iterations, where
345/// `prepare` was called once, and `match` was called once (measurements are in
346/// seconds):
347/// @code
348/// Table 2: Performance Cost for 'prepare' using k_JIT_FLAG
349/// +--------------------+-----------------------+-----------------------+
350/// | Pattern | 'prepare' without-JIT | 'prepare' using-JIT |
351/// +====================+=======================+=======================+
352/// | SIMPLE_PATTERN | 0.2514 | 2.1426 (~8.5x) |
353/// +--------------------+-----------------------+-----------------------+
354/// | EMAIL_PATTERN | 0.3386 | 2.5758 (~7.6x) |
355/// +--------------------+-----------------------+-----------------------+
356/// | IP_ADDRESS_PATTERN | 0.3016 | 2.4433 (~8.1x) |
357/// +--------------------+-----------------------+-----------------------+
358/// @endcode
359/// Note that the tests were run on Linux / Intel Xeon CPU (3.47GHz, 64-bit),
360/// compiled with gcc-4.8.2 in optimized mode.
361///
362/// ## Thread Safety {#bdlpcre_regex-thread-safety}
363///
364///
365/// `bdlpcre::RegEx` is *const* *thread-safe*, meaning that accessors may be
366/// invoked concurrently from different threads, but it is not safe to access or
367/// modify a `bdlpcre::RegEx` in one thread while another thread modifies the
368/// same object. Specifically, the `match` method can be called from multiple
369/// threads after the pattern has been prepared.
370///
371/// Note that `bdlpcre::RegEx` incurs some overhead in order to provide
372/// thread-safe pattern matching functionality. To perform the pattern match,
373/// the underlying PCRE2 library requires a set of buffers that cannot be shared
374/// between threads.
375///
376/// The table below demonstrate the difference of invoking the `match` method
377/// from main (thread that invokes `prepare`) and other threads:
378/// @code
379/// Table 3: Performance cost for 'match' in multi-threaded application
380/// +--------------------+-----------------------+----------------------------+
381/// | Pattern | 'match' (main thread) | 'match' (other thread(s)) |
382/// +====================+=======================+============================+
383/// | SIMPLE_PATTERN | 0.0549 (~1.4x) | 0.0759 |
384/// +--------------------+-----------------------+----------------------------+
385/// | EMAIL_PATTERN | 0.0259 (~1.8x) | 0.0464 |
386/// +--------------------+-----------------------+----------------------------+
387/// | IP_ADDRESS_PATTERN | 0.0377 (~1.5x) | 0.0560 |
388/// +--------------------+-----------------------+----------------------------+
389/// @endcode
390/// Note that JIT stack is functionally part of the match context. Using large
391/// JIT stack can incur additional performance penalty in the multi-threaded
392/// applications.
393///
394/// ## Note on Memory Allocation Exceptions {#bdlpcre_regex-note-on-memory-allocation-exceptions}
395///
396///
397/// PCRE2 library supports memory allocation/deallocation functions supplied by
398/// the client. @ref bdlpcre_regex provides wrappers around `bslma` allocators
399/// that are called from the context of the PCRE2 library (C linkage). Any
400/// exceptions thrown during memory allocation are caught by the wrapper
401/// functions and are not propagated to the PCRE2 library.
402///
403/// ## Usage {#bdlpcre_regex-usage}
404///
405///
406/// The following snippets of code illustrate using this component to extract
407/// the text of the "Subject:" field from an Internet e-mail message (RFC822).
408/// The following `parseSubject` function accepts an RFC822-compliant message of
409/// a specified length and returns the text of the message's subject in the
410/// `result` "out" parameter:
411/// @code
412/// /// Parse the specified `message` of the specified `messageLength` for
413/// /// the "Subject:" field of `message`. Return 0 on success and load the
414/// /// specified `result` with the text of the subject of `message`; return
415/// /// a non-zero value otherwise with no effect on `result`.
416/// int parseSubject(bsl::string *result,
417/// const char *message,
418/// bsl::size_t messageLength)
419/// {
420/// @endcode
421/// The following is the regular expression that will be used to find the
422/// subject text of `message`. The "?P<subjectText>" syntax, borrowed from
423/// Python, allows us later to refer to a particular matched sub-pattern (i.e.,
424/// the text between the `:` and the `\r` in the "Subject:" field of the header)
425/// by the name `subjectText`:
426/// @code
427/// const char PATTERN[] = "^subject:(?P<subjectText>[^\r]*)";
428/// @endcode
429/// First we compile the `PATTERN`, using the `prepare` method, in order to
430/// match subject strings against it. In the event that `prepare` fails, the
431/// first two arguments will be loaded with diagnostic information (an
432/// informational string and an index into the pattern at which the error
433/// occurred, respectively). Two flags, `RegEx::k_FLAG_CASELESS` and
434/// `RegEx::k_FLAG_MULTILINE`, are used in preparing the pattern since Internet
435/// message headers contain case-insensitive content as well as `\n` characters.
436/// The `prepare` method returns 0 on success, and a non-zero value otherwise:
437/// @code
438/// RegEx regEx;
439/// bsl::string errorMessage;
440/// size_t errorOffset;
441///
442/// int returnValue = regEx.prepare(&errorMessage,
443/// &errorOffset,
444/// PATTERN,
445/// RegEx::k_FLAG_CASELESS |
446/// RegEx::k_FLAG_MULTILINE);
447/// assert(0 == returnValue);
448/// @endcode
449/// Next we call `match` supplying `message` and its length. The `matchVector`
450/// will be populated with (offset, length) pairs describing substrings in
451/// `message` that match the prepared `PATTERN`. All variants of the overloaded
452/// `match` method return the `k_STATUS_SUCCESS` status if a match is found,
453/// `k_STATUS_NO_MATCH` if a match is not found, and some other value if any
454/// error occurs. This value may help us to understand the reason of failure:
455/// @code
456/// bsl::vector<bsl::pair<size_t, size_t> > matchVector;
457/// returnValue = regEx.match(&matchVector, message, messageLength);
458///
459/// if (RegEx::k_STATUS_SUCCESS != returnValue) {
460/// if (RegEx::k_STATUS_NO_MATCH == returnValue) {
461/// // No match.
462/// return returnValue; // RETURN
463/// }
464/// else {
465/// // Some failure occurred during the function call.
466/// bsl::cout << "'RegEx::match' failed with the following"
467/// << " status: "
468/// << returnValue
469/// << bsl::endl;
470/// return returnValue; // RETURN
471/// }
472/// }
473/// @endcode
474/// Then we pass "subjectText" to the `subpatternIndex` method to obtain the
475/// index into `matchVector` that describes how to locate the subject text
476/// within `message`. The text is then extracted from `message` and assigned to
477/// the `result` "out" parameter:
478/// @code
479/// const bsl::pair<size_t, size_t> capturedSubject =
480/// matchVector[regEx.subpatternIndex("subjectText")];
481///
482/// *result = bsl::string(&message[capturedSubject.first],
483/// capturedSubject.second);
484///
485/// return 0;
486/// }
487/// @endcode
488/// The following array contains the sample Internet e-mail message from which
489/// we will extract the subject:
490/// @code
491/// const char RFC822_MESSAGE[] =
492/// "Received: ; Fri, 23 Apr 2004 14:30:00 -0400\r\n"
493/// "Message-ID: <12345@mailgate.bloomberg.net>\r\n"
494/// "Date: Fri, 23 Apr 2004 14:30:00 -0400\r\n"
495/// "From: <someone@bloomberg.net>\r\n"
496/// "To: <someone_else@bloomberg.net>\r\n"
497/// "Subject: This is the subject text\r\n"
498/// "MIME-Version: 1.0\r\n"
499/// "Content-Type: text/plain\r\n"
500/// "\r\n"
501/// "This is the message body.\r\n"
502/// ".\r\n";
503/// @endcode
504/// Finally, we call `parseSubject` to extract the subject from
505/// `RFC822_MESSAGE`. The assertions verify that the subject of the message is
506/// correctly extracted and assigned to the local `subject` variable:
507/// @code
508/// int main()
509/// {
510/// bsl::string subject;
511/// const int returnValue = parseSubject(&subject,
512/// RFC822_MESSAGE,
513/// sizeof(RFC822_MESSAGE) - 1);
514/// assert(0 == returnValue);
515/// assert(" This is the subject text" == subject);
516/// }
517/// @endcode
518///
519/// ### Appendix: Perl Compatibility {#bdlpcre_regex-appendix-perl-compatibility}
520///
521///
522/// This section describes the differences in the ways that PCRE2 and Perl
523/// handle regular expressions. The differences described here are with respect
524/// to Perl versions 5.10 and above.
525///
526/// 1) PCRE2 has only a subset of Perl's Unicode support.
527///
528/// 2) PCRE2 allows repeat quantifiers only on parenthesized assertions, but
529/// they do not mean what you might think. For example, `(?!a){3}` does not
530/// assert that the next three characters are not `"a"`. It just asserts that
531/// the next character is not `"a"` three times (in principle: PCRE2 optimizes
532/// this to run the assertion just once). Perl allows repeat quantifiers on
533/// other assertions such as `\b`, but these do not seem to have any use.
534///
535/// 3) Capturing subpatterns that occur inside negative lookahead assertions are
536/// counted, but their entries in the offsets vector are never set. Perl
537/// sometimes (but not always) sets its numerical variables from inside negative
538/// assertions.
539///
540/// 4) The following Perl escape sequences are not supported: `\l`, `\u`, `\L`,
541/// `\U`, and `\N` when followed by a character name or Unicode value. ('\N' on
542/// its own, matching a non-newline character, is supported.) In fact these are
543/// implemented by Perl's general string-handling and are not part of its
544/// pattern matching engine. If any of these are encountered by PCRE2, an error
545/// is generated by default.
546///
547/// 5) The Perl escape sequences `\p,` `\P,` and `\X` are supported only if
548/// PCRE2 is built with Unicode support. The properties that can be tested with
549/// `\p` and `\P` are limited to the general category properties such as `Lu`
550/// and `Nd`, script names such as Greek or Han, and the derived properties
551/// `Any` and `L&`. PCRE2 does support the `Cs` (surrogate) property, which
552/// Perl does not; the Perl documentation says "Because Perl hides the need for
553/// the user to understand the internal representation of Unicode characters,
554/// there is no need to implement the somewhat messy concept of surrogates."
555///
556/// 6) PCRE2 does support the `\Q...\E` escape for quoting substrings.
557/// Characters in between are treated as literals. This is slightly different
558/// from Perl in that `$` and `@` are also handled as literals inside the
559/// quotes. In Perl, they cause variable interpolation (but of course PCRE2
560/// does not have variables). Note the following examples:
561/// @code
562/// Pattern PCRE2 matches Perl matches
563/// ---------------- ------------- ------------------------------------
564/// \Qabc$xyz\E abc$xyz abc followed by the contents of $xyz
565/// \Qabc\$xyz\E abc\$xyz abc\$xyz
566/// \Qabc\E\$\Qxyz\E abc$xyz abc$xyz
567/// @endcode
568/// The `\Q...\E` sequence is recognized both inside and outside character
569/// classes.
570///
571/// 7) PCRE2 does not support the `(?{code})` and `(??{code})` constructions.
572/// However, there is support for recursive patterns. This is not available in
573/// Perl 5.8, but it is in Perl 5.10.
574///
575/// 8) Subroutine calls (whether recursive or not) are treated as atomic groups.
576/// Atomic recursion is like Python, but unlike Perl. Captured values that are
577/// set outside a subroutine call can be referenced from inside in PCRE2, but
578/// not in Perl.
579///
580/// 9) If any of the backtracking control verbs are used in a subpattern that is
581/// called as a subroutine (whether or not recursively), their effect is
582/// confined to that subpattern; it does not extend to the surrounding pattern.
583/// This is not always the case in Perl. In particular, if `(*THEN)` is present
584/// in a group that is called as a subroutine, its action is limited to that
585/// group, even if the group does not contain any `|` characters. Note that
586/// such subpatterns are processed as anchored at the point where they are
587/// tested.
588///
589/// 10) If a pattern contains more than one backtracking control verb, the first
590/// one that is backtracked onto acts. For example, in the pattern
591/// `A(*COMMIT)B(*PRUNE)C` a failure in `B` triggers `(*COMMIT),` but a failure
592/// in `C` triggers `(*PRUNE)`. Perl's behaviour is more complex; in many cases
593/// it is the same as PCRE2, but there are examples where it differs.
594///
595/// 11) Most backtracking verbs in assertions have their normal actions. They
596/// are not confined to the assertion.
597///
598/// 12) There are some differences that are concerned with the settings of
599/// captured strings when part of a pattern is repeated. For example, matching
600/// `"aba"` against the pattern `/^(a(b)?)+$/` in Perl leaves `$2` unset, but in
601/// PCRE2 it is set to `"b"`.
602///
603/// 13) PCRE2's handling of duplicate subpattern numbers and duplicate
604/// subpattern names is not as general as Perl's. This is a consequence of the
605/// fact the PCRE2 works internally just with numbers, using an external table
606/// to translate between numbers and names. In particular, a pattern such as
607/// `(?|(?<a>A)|(?<b)B)`, where the two capturing parentheses have the same
608/// number but different names, is not supported, and causes an error at compile
609/// time. If it were allowed, it would not be possible to distinguish which
610/// parentheses matched, because both names map to capturing subpattern
611/// number 1. To avoid this confusing situation, an error is given at compile
612/// time.
613///
614/// 14) Perl recognizes comments in some places that PCRE2 does not, for
615/// example, between the `(` and `?` at the start of a subpattern. If the `/x`
616/// modifier is set, Perl allows white space between `(` and `?` (though current
617/// Perls warn that this is deprecated) but PCRE2 never does, even if the
618/// `PCRE2_EXTENDED` option is set.
619///
620/// 15) Perl, when in warning mode, gives warnings for character classes such as
621/// `[A-\d]` or `[a-[:digit:]]`. It then treats the hyphens as literals. PCRE2
622/// has no warning features, so it gives an error in these cases because they
623/// are almost certainly user mistakes.
624///
625/// 16) In PCRE2, the upper/lower case character properties `Lu` and `Ll` are
626/// not affected when case-independent matching is specified. For example,
627/// `\p{Lu}` always matches an upper case letter.
628///
629/// 17) PCRE2 provides some extensions to the Perl regular expression
630/// facilities. This list is with respect to Perl 5.10:
631///
632/// (a) Although lookbehind assertions in PCRE2 must match fixed length strings,
633/// each alternative branch of a lookbehind assertion can match a different
634/// length of string. Perl requires them all to have the same length.
635///
636/// (b) If `PCRE2_DOLLAR_ENDONLY` is set and `PCRE2_MULTILINE` is not set, the
637/// `$` meta-character matches only at the very end of the string.
638///
639/// (c) A backslash followed by a letter with no special meaning is faulted.
640/// (Perl can be made to issue a warning.)
641///
642/// (d) If `PCRE2_UNGREEDY` is set, the greediness of the repetition quantifiers
643/// is inverted, that is, by default they are not greedy, but if followed by a
644/// question mark they are.
645///
646/// (e) `PCRE2_ANCHORED` can be used at matching time to force a pattern to be
647/// tried only at the first matching position in the subject string.
648///
649/// (f) The `PCRE2_NOTBOL`, `PCRE2_NOTEOL`, `PCRE2_NOTEMPTY`,
650/// `PCRE2_NOTEMPTY_ATSTART`, and `PCRE2_NO_AUTO_CAPTURE` options have no Perl
651/// equivalents.
652///
653/// (g) The '\R' escape sequence can be restricted to match only `CR,` `LF,` or
654/// `CRLF` by the `PCRE2_BSR_ANYCRLF` option.
655///
656/// (h) The callout facility is PCRE2-specific.
657///
658/// (i) The partial matching facility is PCRE2-specific.
659///
660/// (j) The alternative matching function (`pcre2_dfa_match()` matches in a
661/// different way and is not Perl-compatible.
662///
663/// (k) PCRE2 recognizes some special sequences such as `(*CR)` at the start of
664/// a pattern that set overall options that cannot be changed within the
665/// pattern.
666///
667/// ### Additional Copyright Notice {#bdlpcre_regex-additional-copyright-notice}
668///
669///
670/// @code
671/// Copyright (c) 1997-2015 University of Cambridge
672/// All rights reserved.
673///
674/// Redistribution and use in source and binary forms, with or without
675/// modification, are permitted provided that the following conditions are met:
676///
677/// * Redistributions of source code must retain the above copyright notice,
678/// this list of conditions and the following disclaimer.
679///
680/// * Redistributions in binary form must reproduce the above copyright
681/// notice, this list of conditions and the following disclaimer in the
682/// documentation and/or other materials provided with the distribution.
683///
684/// * Neither the name of the University of Cambridge nor the names of any
685/// contributors may be used to endorse or promote products derived from
686/// this software without specific prior written permission.
687///
688/// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
689/// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
690/// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
691/// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
692/// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
693/// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
694/// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
695/// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
696/// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
697/// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
698/// POSSIBILITY OF SUCH DAMAGE.
699///
700/// Copyright (c) 1997-2015 University of Cambridge
701/// @endcode
702/// @}
703/** @} */
704/** @} */
705
706/** @addtogroup bdl
707 * @{
708 */
709/** @addtogroup bdlpcre
710 * @{
711 */
712/** @addtogroup bdlpcre_regex
713 * @{
714 */
715
716#include <bdlscm_version.h>
717
718#include <bslma_allocator.h>
719#include <bslma_managedptr.h>
721
722#include <bslmf_enableif.h>
723#include <bslmf_issame.h>
725
727#include <bsls_libraryfeatures.h>
728
729#include <bsl_cstddef.h>
730#include <bsl_string.h>
731#include <bsl_string_view.h>
732#include <bsl_utility.h> // 'bsl::pair'
733#include <bsl_vector.h>
734
735#include <string>
736#include <vector>
737
738#ifndef _PCRE2_H
739#define PCRE2_CODE_UNIT_WIDTH 8
740#define PCRE2_STATIC
741#include <pcre2/pcre2.h>
742#endif
743
744#ifndef BDE_DONT_ALLOW_TRANSITIVE_INCLUDES
745#include <bsls_types.h>
746#endif
747
748
749namespace bdlpcre {
750
751class RegEx_MatchContext;
752
753 // ===========
754 // class RegEx
755 // ===========
756
757/// This class provides a mechanism for compiling and matching regular
758/// expressions. A regular expression approximately compatible with Perl
759/// 5.10 is compiled with the `prepare` method. Subsequently, strings are
760/// matched against the compiled (prepared) pattern using the overloaded `match` and `matchRaw` methods.
761///
762/// \note Note that the underlying implementation
763/// uses the open-source Perl Compatible Regular Expressions (PCRE2) library
764/// that was developed at the University of Cambridge
765/// (`http://www.pcre.org/`).
766///
767/// See @ref bdlpcre_regex
768class RegEx {
769
770 // CLASS DATA
771 static
772 bsls::AtomicOperations::AtomicTypes::Int s_depthLimit; // process-wide
773 // default maximum
774 // evaluation
775 // recursion depth
776
777 // PRIVATE DATA
778 int d_flags; // prepare/match flags
779
780 bsl::string d_pattern; // regular expression pattern
781
782 pcre2_general_context *d_pcre2Context_p; // PCRE2 general context
783
784 pcre2_compile_context *d_compileContext_p; // PCRE2 compile context
785
786 pcre2_code *d_patternCode_p; // PCRE2 compiled pattern
787
788 int d_depthLimit; // evaluation recursion depth
789
790 size_t d_jitStackSize; // PCRE JIT stack size
791
793 d_matchContext; // match context helper
794
795 bslma::Allocator *d_allocator_p; // allocator to supply memory
796
797 private:
798 // NOT IMPLEMENTED
799 RegEx(const RegEx&);
800 RegEx& operator=(const RegEx&);
801
802 // PRIVATE MANIPULATORS
803
804 /// Prepare this regular-expression object with the specified `pattern`,
805 /// `flags`, and `jitStackSize` that indicates the size of the allocated
806 /// JIT stack to be used for `pattern`. On success, put this object
807 /// into the "prepared" state and return 0, with no effect on the
808 /// specified `errorBuffer` and `errorOffset`. Otherwise, (1) put this
809 /// object into the "unprepared" state, (2) load `errorBuffer` with a
810 /// message describing the error detected truncated to the specified
811 /// `errorBufferLength` (including a null terminator), (3) load
812 /// `errorOffset` with the offset in `pattern` at which the error was
813 /// detected, and (4) return a non-zero value.
814 ///
815 /// \pre The behavior is undefined unless `flags` is the bit-wise inclusive-or of 0 or more
816 /// of the following values:
817 /// @code
818 /// k_FLAG_CASELESS
819 /// k_FLAG_DOTMATCHESALL
820 /// k_FLAG_MULTILINE
821 /// k_FLAG_UTF8
822 /// k_FLAG_JIT
823 /// k_FLAG_DUPNAMES
824 /// @endcode
825 ///
826 /// \note Note that the flag `k_FLAG_JIT` is ignored if `isJitAvailable()` is
827 /// `false`.
828 int prepareImp(char *errorBuffer,
829 size_t errorBufferLength,
830 size_t *errorOffset,
831 const char *pattern,
832 int flags,
833 size_t jitStackSize);
834
835 // PRIVATE ACCESSORS
836
837 /// Match the specified `subject`, having the specified `subjectLength`,
838 /// against the pattern held by this regular-expression object
839 /// (`pattern()`). `subject` need not be null-terminated and may
840 /// contain embedded null characters. The specified
841 /// `skipUTF8Validation` flag indicates whether UTF-8 string validity
842 /// checking is skipped. Begin matching at the specified
843 /// `subjectOffset` in `subject`. Return `k_STATUS_SUCCESS` on success,
844 /// `k_STATUS_NO_MATCH` if a match is not found, and another value if an
845 /// error occurs. If the returned status is not `k_STATUS_SUCCESS` or
846 /// `k_STATUS_NO_MATCH` it may match one of specific `k_STATUS_*` error
847 /// return constants defined below (but is not guaranteed to).
848 ///
849 /// \pre The behavior is undefined unless `true == isPrepared()`,
850 /// `subject || 0 == subjectLength`, `subjectOffset <= subjectLength`,
851 /// and `subject` is valid UTF-8 if `pattern()` was prepared with
852 /// `k_FLAG_UTF8` but `false == skipUTF8Validation`.
853 template <class RESULT_EXTRACTOR>
854 int matchImp(const RESULT_EXTRACTOR& extractor,
855 const char *subject,
856 size_t subjectLength,
857 size_t subjectOffset,
858 bool skipUTF8Validation) const;
859
860 /// `namedSubpatterns()` implementation.
861 template <class Vector>
862 void namedSubpatternsImp(Vector *result) const;
863
864 /// Replace parts of the specified `subject` that are matched with the
865 /// specified `replacement`. The specified bit mask of `options` flags
866 /// is used to configure the behavior of the replacement. `options`
867 /// should contain a bit-wise OR of the `k_REPLACE_*` constants defined
868 /// by this class, which indicate additional configuration parameters
869 /// for the replacement. If `options` has `k_REPLACE_GLOBAL` flag then
870 /// this function iterates over `subject`, replacing every matching
871 /// substring. If `k_REPLACE_GLOBAL` flag is not set, only the first
872 /// matching substring is replaced. The specified `skipUTF8Validation`
873 /// flag indicates whether UTF-8 `replacment` validity checking is
874 /// skipped. Return the number of substitutions that were carried out,
875 /// and load the specified `result` with the result of the replacement.
876 /// Otherwise, if an error occurs, return a negative value. If that
877 /// error is a syntax error in `replacement`, load the specified
878 /// `errorOffset` (if non-null) with the offset in'replacement' where
879 /// the error was detected; for other errors, such as invalid `subject`
880 /// or `replacement` UTF-8 string, load `errorOffset` with a negative value.
881 ///
882 /// \pre The behavior is undefined unless `true == isPrepared()`.
883 ///
884 /// \note Note that if the size of `result` is too small to fit the resultant
885 /// string then this method computes the size of `result` and adjusts it
886 /// to the size that is needed. To avoid automatic calculation and
887 /// adjustment which may introduce a performace penalty, it is
888 /// recommended that the size of `result` has enough room to fit the
889 /// zero-terminating character.
890 template <class STRING>
891 int replaceImp(STRING *result,
892 int *errorOffset,
893 const bsl::string_view& subject,
894 const bsl::string_view& replacement,
895 size_t options,
896 bool skipUTF8Validation) const;
897
898 public:
899 // TRAITS
901
902 // CONSTANTS
903 enum {
904 // This enumeration defines the flags that may be supplied to 'prepare'
905 // to affect specific pattern matching behavior.
906
907 k_FLAG_CASELESS = 1 << 0, // case-insensitive matching
908
909 k_FLAG_DOTMATCHESALL = 1 << 1, // dot metacharacter matches all chars
910 // (including newlines)
911
912 k_FLAG_MULTILINE = 1 << 2, // multi-line matching
913
914 k_FLAG_UTF8 = 1 << 3, // UTF-8 support
915
916 k_FLAG_JIT = 1 << 4, // just-in-time compiling optimization
917 // requested
918
919 k_FLAG_DUPNAMES = 1 << 5 // allow duplicate named groups
920 // (sub-patterns)
921 };
922
923 enum {
924 // This enumeration defines the flags that may be supplied to 'replace'
925 // to affect specific replacement behavior.
926
927 k_REPLACE_LITERAL = 1 << 0, // the replacement string is literal
928
929 k_REPLACE_GLOBAL = 1 << 1, // replace all occurrences in the
930 // subject
931
932 k_REPLACE_EXTENDED = 1 << 2, // do extended replacement
933 // processing
934
935 k_REPLACE_UNKNOWN_UNSET = 1 << 3, // treat unknown group as unset
936
937 k_REPLACE_UNSET_EMPTY = 1 << 4 // simple unset insert = empty
938 // string
939 };
940
941 enum {
942 // Enumeration used to distinguish among results of match operations.
943
944 /// successful completion of the operation
946
947 /// the subject string did not match the pattern
949
950 /// `depthLimit()` was exceeded
952
953 /// memory available for the JIT stack is not large enough
954 /// (applicable only if `pattern()` was prepared with `k_FLAG_JIT`)
956
957 /// the UTF-8 string ends with a truncated UTF-8 character
959
960 /// the two most significant bits of the 2nd, 3rd or 4th byte of the
961 /// UTF-8 character do not have the binary value 0b10
963
964 /// a UTF-8 character is either 5 or 6 bytes long
966
967 /// a 4-byte UTF-8 character has a value greater than 0x10ffff
969
970 /// a 3-byte UTF-8 character has a value in the range 0xd800 to
971 /// 0xdfff
973
974 /// a 2-, 3- or 4-byte UTF-8 character is "overlong", i.e. it codes
975 /// for a value that can be represented by fewer bytes
977
978 /// the two most significant bits of the first byte of a UTF-8
979 /// character have the binary value 0b10
981
982 /// the first byte of a UTF-8 character has the value 0xfe or 0xff
984 };
985
986 /// Value used to denote an invalid offset for match methods returning
987 /// pairs.
988 static const size_t k_INVALID_OFFSET;
989
990 // CLASS METHODS
991
992 /// Return the process-wide default evaluation recursion depth limit.
993 static int defaultDepthLimit();
994
995 /// Return `true` if just-in-time compiling optimization is supported by current hardware platform and `false` otherwise.
996 ///
997 /// \note Note that JIT
998 /// support is limited to the following hardware platforms:
999 /// @code
1000 /// ARM 32-bit (v5, v7, and Thumb2)
1001 /// ARM 64-bit
1002 /// Intel x86 32-bit and 64-bit
1003 /// MIPS 32-bit and 64-bit
1004 /// Power PC 32-bit and 64-bit
1005 /// SPARC 32-bit
1006 /// @endcode
1007 static bool isJitAvailable();
1008
1009 /// Set the process-wide default evaluation recursion depth limit to the
1010 /// specified `depthLimit`. Return the previous depth limit.
1011 static int setDefaultDepthLimit(int depthLimit);
1012
1013 // CREATORS
1014
1015 /// Create a regular-expression object in the "unprepared" state.
1016 /// Optionally specify a `basicAllocator` used to supply memory. The
1017 /// alignment strategy of the allocator must be "maximum" or "natural".
1018 /// If `basicAllocator` is 0, the currently installed default allocator
1019 /// is used.
1020 RegEx(bslma::Allocator *basicAllocator = 0); // IMPLICIT
1021
1022 /// Destroy this regular-expression object.
1023 ~RegEx();
1024
1025 // MANIPULATORS
1026
1027 /// Free resources used by this regular-expression object and put this
1028 /// object into the "unprepared" state. This method has no effect if
1029 /// this object is already in the "unprepared" state.
1030 void clear();
1031
1032 int prepare(bsl::nullptr_t errorMessage,
1033 size_t *errorOffset,
1034 const char *pattern,
1035 int flags = 0,
1036 size_t jitStackSize = 0);
1037
1038 /// Prepare this regular-expression object with the specified `pattern`
1039 /// and the optionally specified `flags`. `flags`, if supplied, should
1040 /// contain a bit-wise or of the `k_FLAG_*` constants defined by this
1041 /// class, which indicate additional configuration parameters for the
1042 /// regular expression. Optionally specify `jitStackSize`. If `flags`
1043 /// has the `k_FLAG_JIT` flag set, `jitStackSize` indicates the size of
1044 /// the allocated JIT stack to be used for this pattern. If `flags`
1045 /// has the `k_FLAG_JIT` bit set and `jitStackSize` is 0 (or not
1046 /// supplied), no memory will be allocated for the JIT stack and the
1047 /// program stack will be used as the JIT stack. If `flags` does not
1048 /// have `k_FLAG_JIT` set, or `isJitAvailable()` is `false`, the
1049 /// `jitStackSize` parameter, if supplied, is ignored. On success, put
1050 /// this object into the "prepared" state and return 0, with no effect
1051 /// on the specified `errorMessage` and `errorOffset`. Otherwise, (1)
1052 /// put this object into the "unprepared" state, (2) load `errorMessage`
1053 /// (if non-null) with a string describing the error detected, (3) load
1054 /// `errorOffset` (if non-null) with the offset in `pattern` at which
1055 /// the error was detected, and (4) return a non-zero value.
1056 ///
1057 /// \pre The behavior is undefined unless `flags` is the bit-wise inclusive-or of
1058 /// 0 or more of the following values:
1059 /// @code
1060 /// k_FLAG_CASELESS
1061 /// k_FLAG_DOTMATCHESALL
1062 /// k_FLAG_MULTILINE
1063 /// k_FLAG_UTF8
1064 /// k_FLAG_JIT
1065 /// k_FLAG_DUPNAMES
1066 /// @endcode
1067 ///
1068 /// \note Note that the flag `k_FLAG_JIT` is ignored if `isJitAvailable()` is
1069 /// `false`.
1070 template <class STRING>
1073#ifdef BSLS_LIBRARYFEATURES_HAS_CPP17_PMR_STRING
1075#endif
1076 , int>::type
1077 prepare(STRING *errorMessage,
1078 size_t *errorOffset,
1079 const char *pattern,
1080 int flags = 0,
1081 size_t jitStackSize = 0);
1082
1083 /// Set the evaluation recursion depth limit for this regular-expression
1084 /// object to the specified `depthLimit`. Return the previous depth
1085 /// limit.
1087
1088 // ACCESSORS
1089
1090 /// Return the evaluation recursion depth limit for this
1091 /// regular-expression object.
1092 int depthLimit() const;
1093
1094 /// Return the flags that were supplied to the most recent successful
1095 /// call to the `prepare` method of this regular-expression object.
1096 ///
1097 /// \pre The behavior is undefined unless `isPrepared() == true`.
1098 /// \note Note that the
1099 /// returned value will be the bit-wise inclusive-or of 0 or more of the
1100 /// following values:
1101 /// @code
1102 /// k_FLAG_CASELESS
1103 /// k_FLAG_DOTMATCHESALL
1104 /// k_FLAG_MULTILINE
1105 /// k_FLAG_UTF8
1106 /// k_FLAG_JIT
1107 /// k_FLAG_DUPNAMES
1108 /// @endcode
1109 /// Also note that `k_FLAG_JIT` is ignored, but still returned by this
1110 /// method, if `isJitAvailable()` is `false`.
1111 int flags() const;
1112
1113 /// Return `true` if this regular-expression object is in the "prepared"
1114 /// state, and `false` otherwise.
1115 bool isPrepared() const;
1116
1117 /// Return the size of the dynamically allocated JIT stack if it has
1118 /// been specified explicitly with the `prepare` method. Return 0 if a
1119 /// zero `jitStackSize` value was passed to the `prepare` method (or not
1120 /// supplied at all) or if `isPrepared()` is `false`.
1121 size_t jitStackSize() const;
1122
1123 /// Match the specified `subject` against `pattern()`. Begin matching
1124 /// at the optionally specified `subjectOffset` in `subject`. If
1125 /// `subjectOffset` is not specified, matching begins at the start of
1126 /// `subject`. UTF-8 validity checking is performed on `subject` if
1127 /// `pattern()` was prepared with `k_FLAG_UTF8`. Return
1128 /// `k_STATUS_SUCCESS` on success, `k_STATUS_NO_MATCH` if a match is not
1129 /// found, and another value if an error occurs. If the returned status
1130 /// is not `k_STATUS_SUCCESS` or `k_STATUS_NO_MATCH` it may match one of
1131 /// specific `k_STATUS_*` error return constants defined above (but is not guaranteed to).
1132 ///
1133 /// \pre The behavior is undefined unless
1134 /// `true == isPrepared()` and `subjectOffset <= subject.length()`.
1135 ///
1136 /// \note Note that JIT optimization is disabled if `pattern()` was prepared
1137 /// with `k_FLAG_UTF8`; use `matchRaw` if JIT is preferred and UTF-8
1138 /// validation of `subject` is not required.
1139 int match(const bsl::string_view& subject,
1140 size_t subjectOffset = 0) const;
1141
1142 /// Match the specified `subject` having the specified `subjectLength`
1143 /// against `pattern()`. Begin matching at the optionally specified
1144 /// `subjectOffset` in `subject`. If `subjectOffset` is not specified,
1145 /// matching begins at the start of `subject`. `subject` may contain
1146 /// embedded null characters. UTF-8 validity checking is performed on
1147 /// `subject` if `pattern()` was prepared with `k_FLAG_UTF8`. Return
1148 /// `k_STATUS_SUCCESS` on success, `k_STATUS_NO_MATCH` if a match is not
1149 /// found, and another value if an error occurs. If the returned status
1150 /// is not `k_STATUS_SUCCESS` or `k_STATUS_NO_MATCH` it may match one of
1151 /// specific `k_STATUS_*` error return constants defined above (but is not guaranteed to).
1152 ///
1153 /// \pre The behavior is undefined unless
1154 /// `true == isPrepared()`, `subject || 0 == subjectLength`, and `subjectOffset <= subjectLength`.
1155 ///
1156 /// \note Note that JIT optimization is
1157 /// disabled if `pattern()` was prepared with `k_FLAG_UTF8`; use
1158 /// `matchRaw` if JIT is preferred and UTF-8 validation of `subject` is
1159 /// not required.
1160 int match(const char *subject,
1161 size_t subjectLength,
1162 size_t subjectOffset = 0) const;
1163
1164 /// Match the specified `subject` having the specified `subjectLength`
1165 /// against `pattern()`. Begin matching at the optionally specified
1166 /// `subjectOffset` in `subject`. If `subjectOffset` is not specified,
1167 /// matching begins at the start of `subject`. `subject` may contain
1168 /// embedded null characters. UTF-8 validity checking is performed on
1169 /// `subject` if `pattern()` was prepared with `k_FLAG_UTF8`. Return
1170 /// `k_STATUS_SUCCESS` on success, `k_STATUS_NO_MATCH` if a match is not
1171 /// found, and another value if an error occurs. If the returned status
1172 /// is not `k_STATUS_SUCCESS` or `k_STATUS_NO_MATCH` it may match one of
1173 /// specific `k_STATUS_*` error return constants defined above (but is
1174 /// not guaranteed to). `result` is unchanged if a value other than `k_STATUS_SUCCESS` is returned.
1175 ///
1176 /// \pre The behavior is undefined unless
1177 /// `true == isPrepared()`, `subject || 0 == subjectLength`, and `subjectOffset <= subjectLength`.
1178 ///
1179 /// \note Note that JIT optimization is
1180 /// disabled if `pattern()` was prepared with `k_FLAG_UTF8`; use
1181 /// `matchRaw` if JIT is preferred and UTF-8 validation of `subject` is
1182 /// not required.
1184 const char *subject,
1185 size_t subjectLength,
1186 size_t subjectOffset = 0) const;
1188 const char *subject,
1189 size_t subjectLength,
1190 size_t subjectOffset = 0) const;
1191
1192 /// Match the specified `subject` against `pattern()`. Begin matching
1193 /// at the optionally specified `subjectOffset` in `subject`. If
1194 /// `subjectOffset` is not specified, matching begins at the start of
1195 /// `subject`. UTF-8 validity checking is performed on `subject` if
1196 /// `pattern()` was prepared with `k_FLAG_UTF8`. Return
1197 /// `k_STATUS_SUCCESS` on success, `k_STATUS_NO_MATCH` if a match is not
1198 /// found, and another value if an error occurs. If the returned status
1199 /// is not `k_STATUS_SUCCESS` or `k_STATUS_NO_MATCH` it may match one of
1200 /// specific `k_STATUS_*` error return constants defined above (but is
1201 /// not guaranteed to). `result` is unchanged if a value other than `k_STATUS_SUCCESS` is returned.
1202 ///
1203 /// \pre The behavior is undefined unless
1204 /// `true == isPrepared()` and `subjectOffset <= subject.length()`.
1205 ///
1206 /// \note Note that JIT optimization is disabled if `pattern()` was prepared
1207 /// with `k_FLAG_UTF8`; use `matchRaw` if JIT is preferred and UTF-8
1208 /// validation of `subject` is not required.
1210 const bsl::string_view& subject,
1211 size_t subjectOffset = 0) const;
1212
1213 /// Match the specified `subject` having the specified `subjectLength`
1214 /// against `pattern()`. Begin matching at the optionally specified
1215 /// `subjectOffset` in `subject`. If `subjectOffset` is not specified,
1216 /// matching begins at the start of `subject`. `subject` may contain
1217 /// embedded null characters. UTF-8 validity checking is performed on
1218 /// `subject` if `pattern()` was prepared with `k_FLAG_UTF8`. On
1219 /// success:
1220 ///
1221 /// 1. Load the first element of the specified `result` with,
1222 /// respectively, a `(offset, length)` pair or a `bslstl::StringRef`
1223 /// indicating the leftmost match of `pattern()`.
1224 /// 2. Load elements of `result` in the range `[1 .. numSubpatterns()]`
1225 /// with, respectively, a `(offset, length)` pair or a
1226 /// `bslstl::StringRef` indicating the respective matches of
1227 /// sub-patterns (unmatched sub-patterns have their respective
1228 /// `result` elements loaded with either the `(k_INVALID_OFFSET, 0)`
1229 /// pair or an empty `bslstl::StringRef`); sub-patterns matching
1230 /// multiple times have their respective `result` elements loaded
1231 /// with the pairs or `bslstl::StringRef` indicating the rightmost
1232 /// match, and return `k_STATUS_SUCCESS`.
1233 ///
1234 /// Otherwise, return `k_STATUS_NO_MATCH` if a match is not found, and
1235 /// another value if an error occurs. If the returned status is not
1236 /// `k_STATUS_SUCCESS` or `k_STATUS_NO_MATCH` it may match one of
1237 /// specific `k_STATUS_*` error return constants defined above (but is
1238 /// not guaranteed to). `result` is unchanged if a value other than `k_STATUS_SUCCESS` is returned.
1239 ///
1240 /// \pre The behavior is undefined unless
1241 /// `true == isPrepared()`, `subject || 0 == subjectLength`, and `subjectOffset <= subjectLength`.
1242 ///
1243 /// \note Note that JIT optimization is
1244 /// disabled if `pattern()` was prepared with `k_FLAG_UTF8`; use
1245 /// `matchRaw` if JIT is preferred and UTF-8 validation of `subject` is
1246 /// not required. Also note that after a successful call, `result` will
1247 /// contain exactly `numSubpatterns() + 1` elements.
1249 const char *subject,
1250 size_t subjectLength,
1251 size_t subjectOffset = 0)
1252 const;
1254 const char *subject,
1255 size_t subjectLength,
1256 size_t subjectOffset = 0)
1257 const;
1258
1260 const bsl::string_view& subject,
1261 size_t subjectOffset = 0) const;
1262 int match(std::vector<bsl::string_view> *result,
1263 const bsl::string_view& subject,
1264 size_t subjectOffset = 0) const;
1265#ifdef BSLS_LIBRARYFEATURES_HAS_CPP17_PMR
1266 int match(std::pmr::vector<bsl::string_view> *result,
1267 const bsl::string_view& subject,
1268 size_t subjectOffset = 0) const;
1269#endif
1270 // Match the specified 'subject' against 'pattern()'. Begin matching
1271 // at the optionally specified 'subjectOffset' in 'subject'. If
1272 // 'subjectOffset' is not specified, matching begins at the start of
1273 // 'subject'. UTF-8 validity checking is performed on 'subject' if
1274 // 'pattern()' was prepared with 'k_FLAG_UTF8'. On success:
1275 //
1276 //: 1 Load the first element of the specified 'result' with a
1277 //: 'bsl::string_view' indicating the leftmost match of 'pattern()'.
1278 //:
1279 //: 2 Load elements of 'result' in the range '[1 .. numSubpatterns()]'
1280 //: with a 'bsl::string_view' indicating the respective matches of
1281 //: sub-patterns (unmatched sub-patterns have their respective
1282 //: 'result' elements loaded with an empty 'bsl::string_view');
1283 //: sub-patterns matching multiple times have their respective
1284 //: 'result' elements loaded with a 'bsl::string_view' indicating the
1285 //: rightmost match, and return 'k_STATUS_SUCCESS'.
1286 //
1287 // Otherwise, return 'k_STATUS_NO_MATCH' if a match is not found, and
1288 // another value if an error occurs. If the returned status is not
1289 // 'k_STATUS_SUCCESS' or 'k_STATUS_NO_MATCH' it may match one of
1290 // specific 'k_STATUS_*' error return constants defined above (but is
1291 // not guaranteed to). 'result' is unchanged if a value other than
1292 // 'k_STATUS_SUCCESS' is returned. The behavior is undefined unless
1293 // 'true == isPrepared()' and 'subjectOffset <= subject.length()'. Note
1294 // that JIT optimization is disabled if 'pattern()' was prepared with
1295 // 'k_FLAG_UTF8'; use 'matchRaw' if JIT is preferred and UTF-8
1296 // validation of 'subject' is not required. Also note that after a
1297 // successful call, 'result' will contain exactly
1298 // 'numSubpatterns() + 1' elements.
1299
1300 /// Match the specified `subject` against `pattern()`. Begin matching
1301 /// at the optionally specified `subjectOffset` in `subject`. If
1302 /// `subjectOffset` is not specified, matching begins at the start of
1303 /// `subject`. Return `k_STATUS_SUCCESS` on success,
1304 /// `k_STATUS_NO_MATCH` if a match is not found, and another value if an
1305 /// error occurs. If the returned status is not `k_STATUS_SUCCESS` or
1306 /// `k_STATUS_NO_MATCH` it may match one of specific `k_STATUS_*` error
1307 /// return constants defined above (but is not guaranteed to).
1308 ///
1309 /// \pre The behavior is undefined unless `true == isPrepared()`,
1310 /// `subjectOffset <= subject.length()`, and `subject` is valid UTF-8 if
1311 /// `pattern()` was prepared with `k_FLAG_UTF8`.
1312 int matchRaw(const bsl::string_view& subject,
1313 size_t subjectOffset = 0) const;
1314
1315 /// Match the specified `subject` having the specified `subjectLength`
1316 /// against `pattern()`. Begin matching at the optionally specified
1317 /// `subjectOffset` in `subject`. If `subjectOffset` is not specified,
1318 /// matching begins at the start of `subject`. `subject` may contain
1319 /// embedded null characters. Return `k_STATUS_SUCCESS` on success,
1320 /// `k_STATUS_NO_MATCH` if a match is not found, and another value if an
1321 /// error occurs. If the returned status is not `k_STATUS_SUCCESS` or
1322 /// `k_STATUS_NO_MATCH` it may match one of specific `k_STATUS_*` error
1323 /// return constants defined above (but is not guaranteed to).
1324 ///
1325 /// \pre The behavior is undefined unless `true == isPrepared()`,
1326 /// `subject || 0 == subjectLength`, `subjectOffset <= subjectLength`,
1327 /// and `subject` is valid UTF-8 if `pattern()` was prepared with
1328 /// `k_FLAG_UTF8`.
1329 int matchRaw(const char *subject,
1330 size_t subjectLength,
1331 size_t subjectOffset = 0) const;
1332
1333 /// Match the specified `subject` having the specified `subjectLength`
1334 /// against `pattern()`. Begin matching at the optionally specified
1335 /// `subjectOffset` in `subject`. If `subjectOffset` is not specified,
1336 /// matching begins at the start of `subject`. `subject` may contain
1337 /// embedded null characters. Return `k_STATUS_SUCCESS` on success,
1338 /// `k_STATUS_NO_MATCH` if a match is not found, and another value if an
1339 /// error occurs. If the returned status is not `k_STATUS_SUCCESS` or
1340 /// `k_STATUS_NO_MATCH` it may match one of specific `k_STATUS_*` error
1341 /// return constants defined above (but is not guaranteed to). `result`
1342 /// is unchanged if a value other than `k_STATUS_SUCCESS` is returned.
1343 ///
1344 /// \pre The behavior is undefined unless `true == isPrepared()`,
1345 /// `subject || 0 == subjectLength`, `subjectOffset <= subjectLength`,
1346 /// and `subject` is valid UTF-8 if `pattern()` was prepared with
1347 /// `k_FLAG_UTF8`.
1349 const char *subject,
1350 size_t subjectLength,
1351 size_t subjectOffset = 0) const;
1353 const char *subject,
1354 size_t subjectLength,
1355 size_t subjectOffset = 0) const;
1356
1357 /// Match the specified `subject` against `pattern()`. Begin matching
1358 /// at the optionally specified `subjectOffset` in `subject`. If
1359 /// `subjectOffset` is not specified, matching begins at the start of
1360 /// `subject`. Return `k_STATUS_SUCCESS` on success,
1361 /// `k_STATUS_NO_MATCH` if a match is not found, and another value if an
1362 /// error occurs. If the returned status is not `k_STATUS_SUCCESS` or
1363 /// `k_STATUS_NO_MATCH` it may match one of specific `k_STATUS_*` error
1364 /// return constants defined above (but is not guaranteed to). `result`
1365 /// is unchanged if a value other than `k_STATUS_SUCCESS` is returned.
1366 ///
1367 /// \pre The behavior is undefined unless `true == isPrepared()`,
1368 /// `subjectOffset <= subject.length()`, and `subject` is valid UTF-8 if
1369 /// `pattern()` was prepared with `k_FLAG_UTF8`.
1371 const bsl::string_view& subject,
1372 size_t subjectOffset = 0) const;
1373
1374 /// Match the specified `subject` having the specified `subjectLength`
1375 /// against `pattern()`. Begin matching at the optionally specified
1376 /// `subjectOffset` in `subject`. If `subjectOffset` is not specified,
1377 /// matching begins at the start of `subject`. `subject` may contain
1378 /// embedded null characters. On success:
1379 ///
1380 /// 1. Load the first element of the specified `result` with,
1381 /// respectively, a `(offset, length)` pair or a `bslstl::StringRef`
1382 /// indicating the leftmost match of `pattern()`.
1383 /// 2. Load elements of `result` in the range `[1 .. numSubpatterns()]`
1384 /// with, respectively, a `(offset, length)` pair or a
1385 /// `bslstl::StringRef` indicating the respective matches of
1386 /// sub-patterns (unmatched sub-patterns have their respective
1387 /// `result` elements loaded with either the `(k_INVALID_OFFSET, 0)`
1388 /// pair or an empty `bslstl::StringRef`); sub-patterns matching
1389 /// multiple times have their respective `result` elements loaded
1390 /// with the pairs or `bslstl::StringRef` indicating the rightmost
1391 /// match, and return `k_STATUS_SUCCESS`.
1392 ///
1393 /// Otherwise, return `k_STATUS_NO_MATCH` if a match is not found, and
1394 /// another value if an error occurs. If the returned status is not
1395 /// `k_STATUS_SUCCESS` or `k_STATUS_NO_MATCH` it may match one of
1396 /// specific `k_STATUS_*` error return constants defined above (but is
1397 /// not guaranteed to). `result` is unchanged if a value other than `k_STATUS_SUCCESS` is returned.
1398 ///
1399 /// \pre The behavior is undefined unless
1400 /// `true == isPrepared()`, `subject || 0 == subjectLength`,
1401 /// `subjectOffset <= subjectLength`, and `subject` is valid UTF-8 if `pattern()` was prepared with `k_FLAG_UTF8`.
1402 ///
1403 /// \note Note that after a
1404 /// successful call, `result` will contain exactly
1405 /// `numSubpatterns() + 1` elements.
1407 const char *subject,
1408 size_t subjectLength,
1409 size_t subjectOffset = 0)
1410 const;
1412 const char *subject,
1413 size_t subjectLength,
1414 size_t subjectOffset = 0)
1415 const;
1416
1418 const bsl::string_view& subject,
1419 size_t subjectOffset = 0)
1420 const;
1421 int matchRaw(std::vector<bsl::string_view> *result,
1422 const bsl::string_view& subject,
1423 size_t subjectOffset = 0)
1424 const;
1425#ifdef BSLS_LIBRARYFEATURES_HAS_CPP17_PMR
1426 int matchRaw(std::pmr::vector<bsl::string_view> *result,
1427 const bsl::string_view& subject,
1428 size_t subjectOffset = 0)
1429 const;
1430#endif
1431 // Match the specified 'subject' against 'pattern()'. Begin matching
1432 // at the optionally specified 'subjectOffset' in 'subject'. If
1433 // 'subjectOffset' is not specified, matching begins at the start of
1434 // 'subject'. On success:
1435 //
1436 //: 1 Load the first element of the specified 'result' with a
1437 //: 'bsl::string_view' indicating the leftmost match of 'pattern()'.
1438 //:
1439 //: 2 Load elements of 'result' in the range '[1 .. numSubpatterns()]'
1440 //: with a 'bsl::string_view' indicating the respective matches of
1441 //: sub-patterns (unmatched sub-patterns have their respective
1442 //: 'result' elements loaded with an empty 'bsl::string_view');
1443 //: sub-patterns matching multiple times have their respective
1444 //: 'result' elements loaded with a 'bsl::string_view' indicating the
1445 //: rightmost match, and return 'k_STATUS_SUCCESS'.
1446 //
1447 // Otherwise, return 'k_STATUS_NO_MATCH' if a match is not found, and
1448 // another value if an error occurs. If the returned status is not
1449 // 'k_STATUS_SUCCESS' or 'k_STATUS_NO_MATCH' it may match one of
1450 // specific 'k_STATUS_*' error return constants defined above (but is
1451 // not guaranteed to). 'result' is unchanged if a value other than
1452 // 'k_STATUS_SUCCESS' is returned. The behavior is undefined unless
1453 // 'true == isPrepared()', 'subjectOffset <= subject.length()', and
1454 // 'subject' is valid UTF-8 if 'pattern()' was prepared with
1455 // 'k_FLAG_UTF8'. Also note that after a successful call, 'result'
1456 // will contain exactly 'numSubpatterns() + 1' elements.
1457
1461 std::vector<std::pair<bsl::string_view, int> > *result) const;
1462#ifdef BSLS_LIBRARYFEATURES_HAS_CPP17_PMR
1463 void namedSubpatterns(
1464 std::pmr::vector<std::pair<bsl::string_view, int> > *result) const;
1465#endif
1466 // Load into the specified 'result' the mapping between the sub-pattern
1467 // names and their indices. The names are in alphabetical order. If
1468 // duplicate named groups were enabled for this regular expression (see
1469 // component documentation for {Allow Duplicate Named Groups
1470 // (sub-patterns)} then a sub-pattern name may appear multiple times.
1471 // The behavior is undefined unless 'isPrepared()' is 'true'.
1472
1473 /// Return the number of sub-patterns in the pattern held by this
1474 /// regular-expression object (`pattern()`).
1475 ///
1476 /// \pre The behavior is undefined unless `isPrepared() == true`.
1477 int numSubpatterns() const;
1478
1479 /// Return a reference to the non-modifiable pattern held by this regular-expression object.
1480 ///
1481 /// \pre The behavior is undefined unless
1482 /// `isPrepared() == true`.
1483 const bsl::string& pattern() const;
1484
1485 /// Replace parts of the specified `subject` that are matched with the
1486 /// specified `replacement`. Optionally specify a bit mask of `options`
1487 /// flags that configure the behavior of the replacement. `options` should
1488 /// contain a bit-wise OR of the `k_REPLACE_*` constants defined by this
1489 /// class, which indicate additional configuration parameters for the
1490 /// replacement. If `options` has `k_REPLACE_GLOBAL` flag then this
1491 /// function iterates over `subject`, replacing every matching substring.
1492 /// If `k_REPLACE_GLOBAL` flag is not set, only the first matching
1493 /// substring is replaced. UTF-8 validity checking is performed on
1494 /// `subject` and `replacement` if `pattern()` was prepared with
1495 /// `k_FLAG_UTF8`. Return the number of substitutions that were carried
1496 /// out on success, and load the specified `result` with the result of the
1497 /// replacement. Otherwise, if an error occurs, return a negative value.
1498 /// If that error is a syntax error in `replacement`, load the specified
1499 /// `errorOffset` (if non-null) with the offset in `replacement` where the
1500 /// error was detected; for other errors, such as invalid `subject` or
1501 /// `replacement` UTF-8 string, load `errorOffset` with a negative value.
1502 ///
1503 /// \pre The behavior is undefined unless `true == isPrepared()`.
1504 /// \note Note that if
1505 /// the size of `result` is too small to fit the resultant string then this
1506 /// method computes the size of `result` and adjusts it to the size that is
1507 /// needed. To avoid automatic calculation and adjustment which may
1508 /// introduce a performance penalty, it is recommended that the size of
1509 /// `result` has enough room to fit the resulting string including a
1510 /// zero-terminating character.
1512 int *errorOffset,
1513 const bsl::string_view& subject,
1514 const bsl::string_view& replacement,
1515 size_t options = 0) const;
1516 int replace(std::string *result,
1517 int *errorOffset,
1518 const bsl::string_view& subject,
1519 const bsl::string_view& replacement,
1520 size_t options = 0) const;
1521#ifdef BSLS_LIBRARYFEATURES_HAS_CPP17_PMR_STRING
1522 int replace(std::pmr::string *result,
1523 int *errorOffset,
1524 const bsl::string_view& subject,
1525 const bsl::string_view& replacement,
1526 size_t options = 0) const;
1527#endif
1528
1529 /// Replace parts of the specified `subject` that are matched with the
1530 /// specified `replacement`. Optionally specify a bit mask of `options`
1531 /// flags that configure the behavior of the replacement. `options`
1532 /// should contain a bit-wise OR of the `k_REPLACE_*` constants defined
1533 /// by this class, which indicate additional configuration parameters
1534 /// for the replacement. If `options` has `k_REPLACE_GLOBAL` flag then
1535 /// this function iterates over `subject`, replacing every matching
1536 /// substring. If `k_REPLACE_GLOBAL` flag is not set, only the first
1537 /// matching substring is replaced. UTF-8 validity checking is
1538 /// performed on `subject` if `pattern()` was prepared with
1539 /// `k_FLAG_UTF8`. Return the number of substitutions that were carried
1540 /// out on success, and load the specified `result` with the result of
1541 /// the replacement. Otherwise, if an error occurs, return a negative
1542 /// value. If that error is a syntax error in `replacement`, load the
1543 /// specified `errorOffset` (if non-null) with the offset in
1544 /// `replacement` where the error was detected; for other errors, such
1545 /// as invalid `subject` UTF-8 string, load `errorOffset` with a negative value.
1546 ///
1547 /// \pre The behavior is undefined unless `true == isPrepared()`.
1548 ///
1549 /// \note Note that if the size of `result` is too
1550 /// small to fit the resultant string then this method computes the size
1551 /// of `result` and adjusts it to the size that is needed. To avoid
1552 /// automatic calculation and adjustment which may introduce a
1553 /// performance penalty, it is recommended that the size of `result` has
1554 /// enough room to fit the resulting string including a zero-terminating
1555 /// character.
1557 int *errorOffset,
1558 const bsl::string_view& subject,
1559 const bsl::string_view& replacement,
1560 size_t options = 0) const;
1561 int replaceRaw(std::string *result,
1562 int *errorOffset,
1563 const bsl::string_view& subject,
1564 const bsl::string_view& replacement,
1565 size_t options = 0) const;
1566#ifdef BSLS_LIBRARYFEATURES_HAS_CPP17_PMR_STRING
1567 int replaceRaw(std::pmr::string *result,
1568 int *errorOffset,
1569 const bsl::string_view& subject,
1570 const bsl::string_view& replacement,
1571 size_t options = 0) const;
1572#endif
1573
1574 /// Return the 1-based index of the sub-pattern having the specified
1575 /// `name` in the pattern held by this regular-expression object
1576 /// (`pattern()`); return -1 if `pattern()` does not contain a
1577 /// sub-pattern identified by `name` or `name` is not unique.
1578 ///
1579 /// \pre The behavior is undefined unless `isPrepared() == true`.
1580 /// \note Note that the
1581 /// returned value is intended to be used as an index into the
1582 /// `bsl::vector<bsl::pair<int, int> >` returned by `match`. Also note
1583 /// that the function `namedSubpatterns` can be used to find the
1584 /// sub-pattern index when there are duplicate named sub-patterns.
1585 int subpatternIndex(const char *name) const;
1586};
1587
1588// ============================================================================
1589// INLINE DEFINITIONS
1590// ============================================================================
1591
1592 // -----------
1593 // class RegEx
1594 // -----------
1595
1596// CLASS METHODS
1597inline
1599{
1600 return bsls::AtomicOperations::getIntRelaxed(&s_depthLimit);
1601}
1602
1603inline
1605{
1606 int previous = defaultDepthLimit();
1607
1609
1610 return previous;
1611}
1612
1613// CREATORS
1614inline
1616{
1617 clear();
1618 pcre2_compile_context_free(d_compileContext_p);
1619 pcre2_general_context_free(d_pcre2Context_p);
1620}
1621
1622// MANIPULATORS
1623template <class STRING>
1626#ifdef BSLS_LIBRARYFEATURES_HAS_CPP17_PMR_STRING
1628#endif
1629 , int>::type
1630RegEx::prepare(STRING *errorMessage,
1631 size_t *errorOffset,
1632 const char *pattern,
1633 int flags,
1634 size_t jitStackSize)
1635{
1636 const int k_BUFFER_LEN = 256;
1637 char buffer[k_BUFFER_LEN] = {0};
1638 size_t offset;
1639
1640 int ret = prepareImp(&buffer[0],
1641 k_BUFFER_LEN - 1,
1642 &offset,
1643 pattern,
1644 flags,
1645 jitStackSize);
1646
1647 if (ret) {
1648 if (errorMessage) {
1649 errorMessage->assign(&buffer[0]);
1650 }
1651 if (errorOffset) {
1652 *errorOffset = offset;
1653 }
1654 }
1655
1656 return ret;
1657}
1658
1659// ACCESSORS
1660inline
1662{
1663 return d_depthLimit;
1664}
1665
1666inline
1667int RegEx::flags() const
1668{
1669 return d_flags;
1670}
1671
1672inline
1674{
1675 return (0 != d_patternCode_p);
1676}
1677
1678inline
1680{
1681 return d_jitStackSize;
1682}
1683
1684inline
1686{
1687 return d_pattern;
1688}
1689
1690} // close package namespace
1691
1692
1693
1694#endif
1695
1696// ----------------------------------------------------------------------------
1697// Copyright 2016 Bloomberg Finance L.P.
1698//
1699// Licensed under the Apache License, Version 2.0 (the "License");
1700// you may not use this file except in compliance with the License.
1701// You may obtain a copy of the License at
1702//
1703// http://www.apache.org/licenses/LICENSE-2.0
1704//
1705// Unless required by applicable law or agreed to in writing, software
1706// distributed under the License is distributed on an "AS IS" BASIS,
1707// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1708// See the License for the specific language governing permissions and
1709// limitations under the License.
1710// ----------------------------- END-OF-FILE ----------------------------------
1711
1712/** @} */
1713/** @} */
1714/** @} */
Definition bdlpcre_regex.h:768
void namedSubpatterns(std::vector< std::pair< bsl::string_view, int > > *result) const
int matchRaw(std::vector< bsl::string_view > *result, const bsl::string_view &subject, size_t subjectOffset=0) const
int setDepthLimit(int depthLimit)
int match(bsl::string_view *result, const bsl::string_view &subject, size_t subjectOffset=0) const
int matchRaw(const bsl::string_view &subject, size_t subjectOffset=0) const
int matchRaw(bsl::vector< bsl::string_view > *result, const bsl::string_view &subject, size_t subjectOffset=0) const
static const size_t k_INVALID_OFFSET
Definition bdlpcre_regex.h:988
int match(bsl::pair< size_t, size_t > *result, const char *subject, size_t subjectLength, size_t subjectOffset=0) const
int matchRaw(bsl::pair< size_t, size_t > *result, const char *subject, size_t subjectLength, size_t subjectOffset=0) const
static bool isJitAvailable()
int matchRaw(bsl::string_view *result, const bsl::string_view &subject, size_t subjectOffset=0) const
@ k_STATUS_UTF8_TRUNCATED_CHARACTER_FAILURE
the UTF-8 string ends with a truncated UTF-8 character
Definition bdlpcre_regex.h:958
@ k_STATUS_DEPTH_LIMIT_FAILURE
depthLimit() was exceeded
Definition bdlpcre_regex.h:951
@ k_STATUS_UTF8_5_OR_6_BYTES_CHARACTER_FAILURE
a UTF-8 character is either 5 or 6 bytes long
Definition bdlpcre_regex.h:965
@ k_STATUS_UTF8_4_BYTES_CHARACTER_RANGE_FAILURE
a 4-byte UTF-8 character has a value greater than 0x10ffff
Definition bdlpcre_regex.h:968
@ k_STATUS_SUCCESS
successful completion of the operation
Definition bdlpcre_regex.h:945
@ k_STATUS_UTF8_FIRST_BYTE_WRONG_VALUE_FAILURE
the first byte of a UTF-8 character has the value 0xfe or 0xff
Definition bdlpcre_regex.h:983
@ k_STATUS_NO_MATCH
the subject string did not match the pattern
Definition bdlpcre_regex.h:948
@ k_STATUS_UTF8_SIGNIFICANT_BITS_VALUE_FAILURE
Definition bdlpcre_regex.h:962
@ k_STATUS_UTF8_3_BYTES_CHARACTER_RANGE_FAILURE
Definition bdlpcre_regex.h:972
@ k_STATUS_UTF8_FIRST_BYTE_SIGNIFICANT_BITS_FAILURE
Definition bdlpcre_regex.h:980
@ k_STATUS_UTF8_OVERLONG_CHARACTER_FAILURE
Definition bdlpcre_regex.h:976
@ k_STATUS_JIT_STACK_LIMIT_FAILURE
Definition bdlpcre_regex.h:955
int depthLimit() const
Definition bdlpcre_regex.h:1661
@ k_FLAG_JIT
Definition bdlpcre_regex.h:916
@ k_FLAG_CASELESS
Definition bdlpcre_regex.h:907
@ k_FLAG_DUPNAMES
Definition bdlpcre_regex.h:919
@ k_FLAG_MULTILINE
Definition bdlpcre_regex.h:912
@ k_FLAG_UTF8
Definition bdlpcre_regex.h:914
@ k_FLAG_DOTMATCHESALL
Definition bdlpcre_regex.h:909
int prepare(bsl::nullptr_t errorMessage, size_t *errorOffset, const char *pattern, int flags=0, size_t jitStackSize=0)
int replaceRaw(bsl::string *result, int *errorOffset, const bsl::string_view &subject, const bsl::string_view &replacement, size_t options=0) const
int matchRaw(bsl::string_view *result, const char *subject, size_t subjectLength, size_t subjectOffset=0) const
int matchRaw(bsl::vector< bslstl::StringRef > *result, const char *subject, size_t subjectLength, size_t subjectOffset=0) const
BSLMF_NESTED_TRAIT_DECLARATION(RegEx, bslma::UsesBslmaAllocator)
RegEx(bslma::Allocator *basicAllocator=0)
~RegEx()
Destroy this regular-expression object.
Definition bdlpcre_regex.h:1615
int match(bsl::vector< bsl::string_view > *result, const bsl::string_view &subject, size_t subjectOffset=0) const
int replaceRaw(std::string *result, int *errorOffset, const bsl::string_view &subject, const bsl::string_view &replacement, size_t options=0) const
int match(std::vector< bsl::string_view > *result, const bsl::string_view &subject, size_t subjectOffset=0) const
int flags() const
Definition bdlpcre_regex.h:1667
static int defaultDepthLimit()
Return the process-wide default evaluation recursion depth limit.
Definition bdlpcre_regex.h:1598
int match(bsl::vector< bslstl::StringRef > *result, const char *subject, size_t subjectLength, size_t subjectOffset=0) const
const bsl::string & pattern() const
Definition bdlpcre_regex.h:1685
int match(const char *subject, size_t subjectLength, size_t subjectOffset=0) const
int matchRaw(bsl::vector< bsl::pair< size_t, size_t > > *result, const char *subject, size_t subjectLength, size_t subjectOffset=0) const
size_t jitStackSize() const
Definition bdlpcre_regex.h:1679
static int setDefaultDepthLimit(int depthLimit)
Definition bdlpcre_regex.h:1604
void namedSubpatterns(bsl::vector< bsl::pair< bsl::string_view, int > > *result) const
int match(bsl::vector< bsl::pair< size_t, size_t > > *result, const char *subject, size_t subjectLength, size_t subjectOffset=0) const
int match(bsl::string_view *result, const char *subject, size_t subjectLength, size_t subjectOffset=0) const
int match(const bsl::string_view &subject, size_t subjectOffset=0) const
int subpatternIndex(const char *name) const
bool isPrepared() const
Definition bdlpcre_regex.h:1673
int replace(bsl::string *result, int *errorOffset, const bsl::string_view &subject, const bsl::string_view &replacement, size_t options=0) const
int numSubpatterns() const
int matchRaw(const char *subject, size_t subjectLength, size_t subjectOffset=0) const
@ k_REPLACE_UNSET_EMPTY
Definition bdlpcre_regex.h:937
@ k_REPLACE_UNKNOWN_UNSET
Definition bdlpcre_regex.h:935
@ k_REPLACE_GLOBAL
Definition bdlpcre_regex.h:929
@ k_REPLACE_EXTENDED
Definition bdlpcre_regex.h:932
@ k_REPLACE_LITERAL
Definition bdlpcre_regex.h:927
int replace(std::string *result, int *errorOffset, const bsl::string_view &subject, const bsl::string_view &replacement, size_t options=0) const
Definition bslstl_stringview.h:471
Definition bslstl_string.h:1252
Definition bslstl_pair.h:1280
Definition bslstl_vector.h:1120
Definition bslma_allocator.h:545
Definition bslma_managedptr.h:1173
#define BSLS_IDENT(str)
BSLS_IDENT() - insert string into .comment binary segment (if supported)
Definition bsls_ident.h:238
Definition bdlpcre_regex.h:749
BloombergLP::bsls::Nullptr_Impl::Type nullptr_t
Definition bsls_nullptr.h:283
Definition bslmf_enableif.h:530
Definition bslmf_issame.h:146
Definition bslma_usesbslmaallocator.h:344
static void setIntRelaxed(AtomicTypes::Int *atomicInt, int value)
Definition bsls_atomicoperations.h:1554
static int getIntRelaxed(AtomicTypes::Int const *atomicInt)
Definition bsls_atomicoperations.h:1536