Qt
Internal/Contributor docs for the Qt SDK. Note: These are NOT official API docs; those are found at https://doc.qt.io/
Loading...
Searching...
No Matches
qregularexpression.cpp
Go to the documentation of this file.
1// Copyright (C) 2020 Giuseppe D'Angelo <dangelog@gmail.com>.
2// Copyright (C) 2020 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com, author Giuseppe D'Angelo <giuseppe.dangelo@kdab.com>
3// Copyright (C) 2021 The Qt Company Ltd.
4// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
5// Qt-Security score:critical reason:data-parser
6
8
9#include <QtCore/qcoreapplication.h>
10#include <QtCore/qhashfunctions.h>
11#include <QtCore/qlist.h>
12#include <QtCore/qmutex.h>
13#include <QtCore/qstringlist.h>
14#include <QtCore/qdebug.h>
15#include <QtCore/qglobal.h>
16#include <QtCore/qatomic.h>
17#include <QtCore/qdatastream.h>
18
19#if defined(Q_OS_MACOS)
20#include <QtCore/private/qcore_mac_p.h>
21#endif
22
23#define PCRE2_CODE_UNIT_WIDTH 16
24
25#include <pcre2.h>
26
27QT_BEGIN_NAMESPACE
28
29using namespace Qt::StringLiterals;
30
31/*!
32 \class QRegularExpression
33 \inmodule QtCore
34 \reentrant
35
36 \brief The QRegularExpression class provides pattern matching using regular
37 expressions.
38
39 \since 5.0
40
41 \ingroup tools
42 \ingroup shared
43 \ingroup string-processing
44
45 \keyword regular expression
46
47 \compares equality
48 Regular expressions, or \e{regexps}, are a very powerful tool to handle
49 strings and texts. This is useful in many contexts, e.g.,
50
51 \table
52 \row \li Validation
53 \li A regexp can test whether a substring meets some criteria,
54 e.g. is an integer or contains no whitespace.
55 \row \li Searching
56 \li A regexp provides more powerful pattern matching than
57 simple substring matching, e.g., match one of the words
58 \e{mail}, \e{letter} or \e{correspondence}, but none of the
59 words \e{email}, \e{mailman}, \e{mailer}, \e{letterbox}, etc.
60 \row \li Search and Replace
61 \li A regexp can replace all occurrences of a substring with a
62 different substring, e.g., replace all occurrences of \e{&}
63 with \e{\&amp;} except where the \e{&} is already followed by
64 an \e{amp;}.
65 \row \li String Splitting
66 \li A regexp can be used to identify where a string should be
67 split apart, e.g. splitting tab-delimited strings.
68 \endtable
69
70 This document is by no means a complete reference to pattern matching using
71 regular expressions, and the following parts will require the reader to
72 have some basic knowledge about Perl-like regular expressions and their
73 pattern syntax.
74
75 Good references about regular expressions include:
76
77 \list
78 \li \e {Mastering Regular Expressions} (Third Edition) by Jeffrey E. F.
79 Friedl, ISBN 0-596-52812-4;
80 \li the \l{https://pcre.org/original/doc/html/pcrepattern.html}
81 {pcrepattern(3)} man page, describing the pattern syntax supported by PCRE
82 (the reference implementation of Perl-compatible regular expressions);
83 \li the \l{http://perldoc.perl.org/perlre.html} {Perl's regular expression
84 documentation} and the \l{http://perldoc.perl.org/perlretut.html} {Perl's
85 regular expression tutorial}.
86 \endlist
87
88 \section1 Introduction
89
90 QRegularExpression implements Perl-compatible regular expressions. It fully
91 supports Unicode. For an overview of the regular expression syntax
92 supported by QRegularExpression, please refer to the aforementioned
93 pcrepattern(3) man page. A regular expression is made up of two things: a
94 \b{pattern string} and a set of \b{pattern options} that change the
95 meaning of the pattern string.
96
97 You can set the pattern string by passing a string to the QRegularExpression
98 constructor:
99
100 \snippet code/src_corelib_text_qregularexpression.cpp 0
101
102 This sets the pattern string to \c{a pattern}. You can also use the
103 setPattern() function to set a pattern on an existing QRegularExpression
104 object:
105
106 \snippet code/src_corelib_text_qregularexpression.cpp 1
107
108 Note that due to C++ literal strings rules, you must escape all backslashes
109 inside the pattern string with another backslash:
110
111 \snippet code/src_corelib_text_qregularexpression.cpp 2
112
113 Alternatively, you can use a
114 \l {https://en.cppreference.com/w/cpp/language/string_literal} {raw string literal},
115 in which case you don't need to escape backslashes in the pattern, all characters
116 between \c {R"(...)"} are considered raw characters. As you can see in the following
117 example, this simplifies writing patterns:
118
119 \snippet code/src_corelib_text_qregularexpression.cpp 35
120
121 The pattern() function returns the pattern that is currently set for a
122 QRegularExpression object:
123
124 \snippet code/src_corelib_text_qregularexpression.cpp 3
125
126 \section1 Pattern Options
127
128 The meaning of the pattern string can be modified by setting one or more
129 \e{pattern options}. For instance, it is possible to set a pattern to match
130 case insensitively by setting the QRegularExpression::CaseInsensitiveOption.
131
132 You can set the options by passing them to the QRegularExpression
133 constructor, as in:
134
135 \snippet code/src_corelib_text_qregularexpression.cpp 4
136
137 Alternatively, you can use the setPatternOptions() function on an existing
138 QRegularExpressionObject:
139
140 \snippet code/src_corelib_text_qregularexpression.cpp 5
141
142 It is possible to get the pattern options currently set on a
143 QRegularExpression object by using the patternOptions() function:
144
145 \snippet code/src_corelib_text_qregularexpression.cpp 6
146
147 Please refer to the QRegularExpression::PatternOption enum documentation for
148 more information about each pattern option.
149
150 \section1 Match Type and Match Options
151
152 The last two arguments of the match() and the globalMatch() functions set
153 the match type and the match options. The match type is a value of the
154 QRegularExpression::MatchType enum; the "traditional" matching algorithm is
155 chosen by using the NormalMatch match type (the default). It is also
156 possible to enable partial matching of the regular expression against a
157 subject string: see the \l{partial matching} section for more details.
158
159 The match options are a set of one or more QRegularExpression::MatchOption
160 values. They change the way a specific match of a regular expression
161 against a subject string is done. Please refer to the
162 QRegularExpression::MatchOption enum documentation for more details.
163
164 \target normal matching
165 \section1 Normal Matching
166
167 In order to perform a match you can simply invoke the match() function
168 passing a string to match against. We refer to this string as the
169 \e{subject string}. The result of the match() function is a
170 QRegularExpressionMatch object that can be used to inspect the results of
171 the match. For instance:
172
173 \snippet code/src_corelib_text_qregularexpression.cpp 7
174
175 If a match is successful, the (implicit) capturing group number 0 can be
176 used to retrieve the substring matched by the entire pattern (see also the
177 section about \l{extracting captured substrings}):
178
179 \snippet code/src_corelib_text_qregularexpression.cpp 8
180
181 It's also possible to start a match at an arbitrary offset inside the
182 subject string by passing the offset as an argument of the
183 match() function. In the following example \c{"12 abc"}
184 is not matched because the match is started at offset 1:
185
186 \snippet code/src_corelib_text_qregularexpression.cpp 9
187
188 \target extracting captured substrings
189 \section2 Extracting captured substrings
190
191 The QRegularExpressionMatch object contains also information about the
192 substrings captured by the capturing groups in the pattern string. The
193 \l{QRegularExpressionMatch::}{captured()} function will return the string
194 captured by the n-th capturing group:
195
196 \snippet code/src_corelib_text_qregularexpression.cpp 10
197
198 Capturing groups in the pattern are numbered starting from 1, and the
199 implicit capturing group 0 is used to capture the substring that matched
200 the entire pattern.
201
202 It's also possible to retrieve the starting and the ending offsets (inside
203 the subject string) of each captured substring, by using the
204 \l{QRegularExpressionMatch::}{capturedStart()} and the
205 \l{QRegularExpressionMatch::}{capturedEnd()} functions:
206
207 \snippet code/src_corelib_text_qregularexpression.cpp 11
208
209 All of these functions have an overload taking a QString as a parameter
210 in order to extract \e{named} captured substrings. For instance:
211
212 \snippet code/src_corelib_text_qregularexpression.cpp 12
213
214 \target global matching
215 \section1 Global Matching
216
217 \e{Global matching} is useful to find all the occurrences of a given
218 regular expression inside a subject string. Suppose that we want to extract
219 all the words from a given string, where a word is a substring matching
220 the pattern \c{\w+}.
221
222 QRegularExpression::globalMatch returns a QRegularExpressionMatchIterator,
223 which is a Java-like forward iterator that can be used to iterate over the
224 results. For instance:
225
226 \snippet code/src_corelib_text_qregularexpression.cpp 13
227
228 Since it's a Java-like iterator, the QRegularExpressionMatchIterator will
229 point immediately before the first result. Every result is returned as a
230 QRegularExpressionMatch object. The
231 \l{QRegularExpressionMatchIterator::}{hasNext()} function will return true
232 if there's at least one more result, and
233 \l{QRegularExpressionMatchIterator::}{next()} will return the next result
234 and advance the iterator. Continuing from the previous example:
235
236 \snippet code/src_corelib_text_qregularexpression.cpp 14
237
238 You can also use \l{QRegularExpressionMatchIterator::}{peekNext()} to get
239 the next result without advancing the iterator.
240
241 It is also possible to simply use the result of
242 QRegularExpression::globalMatch in a range-based for loop, for instance
243 like this:
244
245 \snippet code/src_corelib_text_qregularexpression.cpp 34
246
247 It is possible to pass a starting offset and one or more match options to
248 the globalMatch() function, exactly like normal matching with match().
249
250 \target partial matching
251 \section1 Partial Matching
252
253 A \e{partial match} is obtained when the end of the subject string is
254 reached, but more characters are needed to successfully complete the match.
255 Note that a partial match is usually much more inefficient than a normal
256 match because many optimizations of the matching algorithm cannot be
257 employed.
258
259 A partial match must be explicitly requested by specifying a match type of
260 PartialPreferCompleteMatch or PartialPreferFirstMatch when calling
261 QRegularExpression::match or QRegularExpression::globalMatch. If a partial
262 match is found, then calling the \l{QRegularExpressionMatch::}{hasMatch()}
263 function on the QRegularExpressionMatch object returned by match() will
264 return \c{false}, but \l{QRegularExpressionMatch::}{hasPartialMatch()} will return
265 \c{true}.
266
267 When a partial match is found, no captured substrings are returned, and the
268 (implicit) capturing group 0 corresponding to the whole match captures the
269 partially matched substring of the subject string.
270
271 Note that asking for a partial match can still lead to a complete match, if
272 one is found; in this case, \l{QRegularExpressionMatch::}{hasMatch()} will
273 return \c{true} and \l{QRegularExpressionMatch::}{hasPartialMatch()}
274 \c{false}. It never happens that a QRegularExpressionMatch reports both a
275 partial and a complete match.
276
277 Partial matching is mainly useful in two scenarios: validating user input
278 in real time and incremental/multi-segment matching.
279
280 \target validating user input
281 \section2 Validating user input
282
283 Suppose that we would like the user to input a date in a specific
284 format, for instance "MMM dd, yyyy". We can check the input validity with
285 a pattern like:
286
287 \c{^(Jan|Feb|Mar|Apr|May|Jun|Jul|Aug|Sep|Oct|Nov|Dec) \d\d?, \d\d\d\d$}
288
289 (This pattern doesn't catch invalid days, but let's keep it for the
290 example's purposes).
291
292 We would like to validate the input with this regular expression \e{while}
293 the user is typing it, so that we can report an error in the input as soon
294 as it is committed (for instance, the user typed the wrong key). In order
295 to do so we must distinguish three cases:
296
297 \list
298 \li the input cannot possibly match the regular expression;
299 \li the input does match the regular expression;
300 \li the input does not match the regular expression right now,
301 but it will if more characters will be added to it.
302 \endlist
303
304 Note that these three cases represent exactly the possible states of a
305 QValidator (see the QValidator::State enum).
306
307 In particular, in the last case we want the regular expression engine to
308 report a partial match: we are successfully matching the pattern against
309 the subject string but the matching cannot continue because the end of the
310 subject is encountered. Notice, however, that the matching algorithm should
311 continue and try all possibilities, and in case a complete (non-partial)
312 match is found, then this one should be reported, and the input string
313 accepted as fully valid.
314
315 This behavior is implemented by the PartialPreferCompleteMatch match type.
316 For instance:
317
318 \snippet code/src_corelib_text_qregularexpression.cpp 15
319
320 If matching the same regular expression against the subject string leads to
321 a complete match, it is reported as usual:
322
323 \snippet code/src_corelib_text_qregularexpression.cpp 16
324
325 Another example with a different pattern, showing the behavior of
326 preferring a complete match over a partial one:
327
328 \snippet code/src_corelib_text_qregularexpression.cpp 17
329
330 In this case, the subpattern \c{abc\\w+X} partially matches the subject
331 string; however, the subpattern \c{def} matches the subject string
332 completely, and therefore a complete match is reported.
333
334 If multiple partial matches are found when matching (but no complete
335 match), then the QRegularExpressionMatch object will report the first one
336 that is found. For instance:
337
338 \snippet code/src_corelib_text_qregularexpression.cpp 18
339
340 \section2 Incremental/multi-segment matching
341
342 Incremental matching is another use case of partial matching. Suppose that
343 we want to find the occurrences of a regular expression inside a large text
344 (that is, substrings matching the regular expression). In order to do so we
345 would like to "feed" the large text to the regular expression engines in
346 smaller chunks. The obvious problem is what happens if the substring that
347 matches the regular expression spans across two or more chunks.
348
349 In this case, the regular expression engine should report a partial match,
350 so that we can match again adding new data and (eventually) get a complete
351 match. This implies that the regular expression engine may assume that
352 there are other characters \e{beyond the end} of the subject string. This
353 is not to be taken literally -- the engine will never try to access
354 any character after the last one in the subject.
355
356 QRegularExpression implements this behavior when using the
357 PartialPreferFirstMatch match type. This match type reports a partial match
358 as soon as it is found, and other match alternatives are not tried
359 (even if they could lead to a complete match). For instance:
360
361 \snippet code/src_corelib_text_qregularexpression.cpp 19
362
363 This happens because when matching the first branch of the alternation
364 operator a partial match is found, and therefore matching stops, without
365 trying the second branch. Another example:
366
367 \snippet code/src_corelib_text_qregularexpression.cpp 20
368
369 This shows what could seem a counterintuitive behavior of quantifiers:
370 since \c{?} is greedy, then the engine tries first to continue the match
371 after having matched \c{"abc"}; but then the matching reaches the end of the
372 subject string, and therefore a partial match is reported. This is
373 even more surprising in the following example:
374
375 \snippet code/src_corelib_text_qregularexpression.cpp 21
376
377 It's easy to understand this behavior if we remember that the engine
378 expects the subject string to be only a substring of the whole text we're
379 looking for a match into (that is, how we said before, that the engine
380 assumes that there are other characters beyond the end of the subject
381 string).
382
383 Since the \c{*} quantifier is greedy, then reporting a complete match could
384 be an error, because after the current subject \c{"abc"} there may be other
385 occurrences of \c{"abc"}. For instance, the complete text could have been
386 "abcabcX", and therefore the \e{right} match to report (in the complete
387 text) would have been \c{"abcabc"}; by matching only against the leading
388 \c{"abc"} we instead get a partial match.
389
390 \section1 Error Handling
391
392 It is possible for a QRegularExpression object to be invalid because of
393 syntax errors in the pattern string. The isValid() function will return
394 true if the regular expression is valid, or false otherwise:
395
396 \snippet code/src_corelib_text_qregularexpression.cpp 22
397
398 You can get more information about the specific error by calling the
399 errorString() function; moreover, the patternErrorOffset() function
400 will return the offset inside the pattern string
401
402 \snippet code/src_corelib_text_qregularexpression.cpp 23
403
404 If a match is attempted with an invalid QRegularExpression, then the
405 returned QRegularExpressionMatch object will be invalid as well (that is,
406 its \l{QRegularExpressionMatch::}{isValid()} function will return false).
407 The same applies for attempting a global match.
408
409 \section1 Unsupported Perl-compatible Regular Expressions Features
410
411 QRegularExpression does not support all the features available in
412 Perl-compatible regular expressions. The most notable one is the fact that
413 duplicated names for capturing groups are not supported, and using them can
414 lead to undefined behavior.
415
416 This may change in a future version of Qt.
417
418 \section1 Debugging Code that Uses QRegularExpression
419
420 QRegularExpression internally uses a just in time compiler (JIT) to
421 optimize the execution of the matching algorithm. The JIT makes extensive
422 usage of self-modifying code, which can lead debugging tools such as
423 Valgrind to crash. You must enable all checks for self-modifying code if
424 you want to debug programs using QRegularExpression (for instance, Valgrind's
425 \c{--smc-check} command line option). The downside of enabling such checks
426 is that your program will run considerably slower.
427
428 To avoid that, the JIT is disabled by default if you compile Qt in debug
429 mode. It is possible to override the default and enable or disable the JIT
430 usage (both in debug or release mode) by setting the
431 \c{QT_ENABLE_REGEXP_JIT} environment variable to a non-zero or zero value
432 respectively.
433
434 \target sec-con-QRegularExpression
435 \section1 Security Considerations
436
437 Only use pattern strings from trusted sources. Attacker-controlled regex
438 patterns are inherently dangerous because they can consume excessive CPU
439 and memory resources, and Qt does not provide robust controls (timeouts,
440 configurable limits, ...) to safely execute arbitrary patterns.
441
442 To use a variable string as part of a pattern, pass the string through
443 escape() first. Then any special characters in it match literally:
444
445 \snippet code/src_corelib_text_qregularexpression.cpp 27
446
447 \sa QRegularExpressionMatch, QRegularExpressionMatchIterator
448*/
449
450/*!
451 \class QRegularExpressionMatch
452 \inmodule QtCore
453 \reentrant
454
455 \brief The QRegularExpressionMatch class provides the results of a matching
456 a QRegularExpression against a string.
457
458 \since 5.0
459
460 \ingroup tools
461 \ingroup shared
462 \ingroup string-processing
463
464 \keyword regular expression match
465
466 A QRegularExpressionMatch object can be obtained by calling the
467 QRegularExpression::match() function, or as a single result of a global
468 match from a QRegularExpressionMatchIterator.
469
470 The success or the failure of a match attempt can be inspected by calling
471 the hasMatch() function. QRegularExpressionMatch also reports a successful
472 partial match through the hasPartialMatch() function.
473
474 In addition, QRegularExpressionMatch returns the substrings captured by the
475 capturing groups in the pattern string. The implicit capturing group with
476 index 0 captures the result of the whole match. The captured() function
477 returns each substring captured, either by the capturing group's index or
478 by its name:
479
480 \snippet code/src_corelib_text_qregularexpression.cpp 29
481
482 For each captured substring it is possible to query its starting and ending
483 offsets in the subject string by calling the capturedStart() and the
484 capturedEnd() function, respectively. The length of each captured
485 substring is available using the capturedLength() function.
486
487 The convenience function capturedTexts() will return \e{all} the captured
488 substrings at once (including the substring matched by the entire pattern)
489 in the order they have been captured by capturing groups; that is,
490 \c{captured(i) == capturedTexts().at(i)}.
491
492 You can retrieve the QRegularExpression object the subject string was
493 matched against by calling the regularExpression() function; the
494 match type and the match options are available as well by calling
495 the matchType() and the matchOptions() respectively.
496
497 Please refer to the QRegularExpression documentation for more information
498 about the Qt regular expression classes.
499
500 \sa QRegularExpression
501*/
502
503/*!
504 \class QRegularExpressionMatchIterator
505 \inmodule QtCore
506 \reentrant
507
508 \brief The QRegularExpressionMatchIterator class provides an iterator on
509 the results of a global match of a QRegularExpression object against a string.
510
511 \since 5.0
512
513 \ingroup tools
514 \ingroup shared
515 \ingroup string-processing
516
517 \keyword regular expression iterator
518
519 A QRegularExpressionMatchIterator object is a forward only Java-like
520 iterator; it can be obtained by calling the
521 QRegularExpression::globalMatch() function. A new
522 QRegularExpressionMatchIterator will be positioned before the first result.
523 You can then call the hasNext() function to check if there are more
524 results available; if so, the next() function will return the next
525 result and advance the iterator.
526
527 Each result is a QRegularExpressionMatch object holding all the information
528 for that result (including captured substrings).
529
530 For instance:
531
532 \snippet code/src_corelib_text_qregularexpression.cpp 30
533
534 Moreover, QRegularExpressionMatchIterator offers a peekNext() function
535 to get the next result \e{without} advancing the iterator.
536
537 Starting with Qt 6.0, it is also possible to simply use the result of
538 QRegularExpression::globalMatch in a range-based for loop, for instance
539 like this:
540
541 \snippet code/src_corelib_text_qregularexpression.cpp 34
542
543 You can retrieve the QRegularExpression object the subject string was
544 matched against by calling the regularExpression() function; the
545 match type and the match options are available as well by calling
546 the matchType() and the matchOptions() respectively.
547
548 Please refer to the QRegularExpression documentation for more information
549 about the Qt regular expression classes.
550
551 \sa QRegularExpression, QRegularExpressionMatch
552*/
553
554
555/*!
556 \enum QRegularExpression::PatternOption
557
558 The PatternOption enum defines modifiers to the way the pattern string
559 should be interpreted, and therefore the way the pattern matches against a
560 subject string.
561
562 \value NoPatternOption
563 No pattern options are set.
564
565 \value CaseInsensitiveOption
566 The pattern should match against the subject string in a case
567 insensitive way. This option corresponds to the /i modifier in Perl
568 regular expressions.
569
570 \value DotMatchesEverythingOption
571 The dot metacharacter (\c{.}) in the pattern string is allowed to match
572 any character in the subject string, including newlines (normally, the
573 dot does not match newlines). This option corresponds to the \c{/s}
574 modifier in Perl regular expressions.
575
576 \value MultilineOption
577 The caret (\c{^}) and the dollar (\c{$}) metacharacters in the pattern
578 string are allowed to match, respectively, immediately after and
579 immediately before any newline in the subject string, as well as at the
580 very beginning and at the very end of the subject string. This option
581 corresponds to the \c{/m} modifier in Perl regular expressions.
582
583 \value ExtendedPatternSyntaxOption
584 Any whitespace in the pattern string which is not escaped and outside a
585 character class is ignored. Moreover, an unescaped sharp (\b{#})
586 outside a character class causes all the following characters, until
587 the first newline (included), to be ignored. This can be used to
588 increase the readability of a pattern string as well as put comments
589 inside regular expressions; this is particularly useful if the pattern
590 string is loaded from a file or written by the user, because in C++
591 code it is always possible to use the rules for string literals to put
592 comments outside the pattern string. This option corresponds to the \c{/x}
593 modifier in Perl regular expressions.
594
595 \value InvertedGreedinessOption
596 The greediness of the quantifiers is inverted: \c{*}, \c{+}, \c{?},
597 \c{{m,n}}, etc. become lazy, while their lazy versions (\c{*?},
598 \c{+?}, \c{??}, \c{{m,n}?}, etc.) become greedy. There is no equivalent
599 for this option in Perl regular expressions.
600
601 \value DontCaptureOption
602 The non-named capturing groups do not capture substrings; named
603 capturing groups still work as intended, as well as the implicit
604 capturing group number 0 corresponding to the entire match. There is no
605 equivalent for this option in Perl regular expressions.
606
607 \value UseUnicodePropertiesOption
608 The meaning of the \c{\w}, \c{\d}, etc., character classes, as well as
609 the meaning of their counterparts (\c{\W}, \c{\D}, etc.), is changed
610 from matching ASCII characters only to matching any character with the
611 corresponding Unicode property. For instance, \c{\d} is changed to
612 match any character with the Unicode Nd (decimal digit) property;
613 \c{\w} to match any character with either the Unicode L (letter) or N
614 (digit) property, plus underscore, and so on. This option corresponds
615 to the \c{/u} modifier in Perl regular expressions.
616*/
617
618/*!
619 \enum QRegularExpression::MatchType
620
621 The MatchType enum defines the type of the match that should be attempted
622 against the subject string.
623
624 \value NormalMatch
625 A normal match is done.
626
627 \value PartialPreferCompleteMatch
628 The pattern string is matched partially against the subject string. If
629 a partial match is found, then it is recorded, and other matching
630 alternatives are tried as usual. If a complete match is then found,
631 then it's preferred to the partial match; in this case only the
632 complete match is reported. If instead no complete match is found (but
633 only the partial one), then the partial one is reported.
634
635 \value PartialPreferFirstMatch
636 The pattern string is matched partially against the subject string. If
637 a partial match is found, then matching stops and the partial match is
638 reported. In this case, other matching alternatives (potentially
639 leading to a complete match) are not tried. Moreover, this match type
640 assumes that the subject string only a substring of a larger text, and
641 that (in this text) there are other characters beyond the end of the
642 subject string. This can lead to surprising results; see the discussion
643 in the \l{partial matching} section for more details.
644
645 \value NoMatch
646 No matching is done. This value is returned as the match type by a
647 default constructed QRegularExpressionMatch or
648 QRegularExpressionMatchIterator. Using this match type is not very
649 useful for the user, as no matching ever happens. This enum value
650 has been introduced in Qt 5.1.
651*/
652
653/*!
654 \enum QRegularExpression::MatchOption
655
656 \value NoMatchOption
657 No match options are set.
658
659 \value AnchoredMatchOption
660 Use AnchorAtOffsetMatchOption instead.
661
662 \value AnchorAtOffsetMatchOption
663 The match is constrained to start exactly at the offset passed to
664 match() in order to be successful, even if the pattern string does not
665 contain any metacharacter that anchors the match at that point.
666 Note that passing this option does not anchor the end of the match
667 to the end of the subject; if you want to fully anchor a regular
668 expression, use anchoredPattern().
669 This enum value has been introduced in Qt 6.0.
670
671 \value DontCheckSubjectStringMatchOption
672 The subject string is not checked for UTF-16 validity before
673 attempting a match. Use this option with extreme caution, as
674 attempting to match an invalid string may crash the program and/or
675 constitute a security issue. This enum value has been introduced in
676 Qt 5.4.
677*/
678
679/*!
680 \internal
681*/
682static int convertToPcreOptions(QRegularExpression::PatternOptions patternOptions)
683{
684 int options = 0;
685
686 if (patternOptions & QRegularExpression::CaseInsensitiveOption)
687 options |= PCRE2_CASELESS;
688 if (patternOptions & QRegularExpression::DotMatchesEverythingOption)
689 options |= PCRE2_DOTALL;
690 if (patternOptions & QRegularExpression::MultilineOption)
691 options |= PCRE2_MULTILINE;
692 if (patternOptions & QRegularExpression::ExtendedPatternSyntaxOption)
693 options |= PCRE2_EXTENDED;
694 if (patternOptions & QRegularExpression::InvertedGreedinessOption)
695 options |= PCRE2_UNGREEDY;
696 if (patternOptions & QRegularExpression::DontCaptureOption)
697 options |= PCRE2_NO_AUTO_CAPTURE;
698 if (patternOptions & QRegularExpression::UseUnicodePropertiesOption)
699 options |= PCRE2_UCP;
700
701 return options;
702}
703
704/*!
705 \internal
706*/
707static int convertToPcreOptions(QRegularExpression::MatchOptions matchOptions)
708{
709 int options = 0;
710
711 if (matchOptions & QRegularExpression::AnchorAtOffsetMatchOption)
712 options |= PCRE2_ANCHORED;
713 if (matchOptions & QRegularExpression::DontCheckSubjectStringMatchOption)
714 options |= PCRE2_NO_UTF_CHECK;
715
716 return options;
717}
718
720{
724
729
734
736 qsizetype offset,
737 CheckSubjectStringOption checkSubjectStringOption = CheckSubjectString,
738 const QRegularExpressionMatchPrivate *previous = nullptr) const;
739
740 int captureIndexForName(QAnyStringView name) const;
741
742 // sizeof(QSharedData) == 4, so start our members with an enum
745
746 // *All* of the following members are managed while holding this mutex,
747 // except for isDirty which is set to true by QRegularExpression setters
748 // (right after a detach happened).
749 mutable QMutex mutex;
750
751 // The PCRE code pointer is reference-counted by the QRegularExpressionPrivate
752 // objects themselves; when the private is copied (i.e. a detach happened)
753 // it is set to nullptr
754 pcre2_code_16 *compiledPattern;
760};
761
763{
764 QRegularExpressionMatchPrivate(const QRegularExpression &re,
765 const QString &subjectStorage,
766 QStringView subject,
767 QRegularExpression::MatchType matchType,
768 QRegularExpression::MatchOptions matchOptions);
769
770 QRegularExpressionMatch nextMatch() const;
771
772 const QRegularExpression regularExpression;
773
774 // subject is what we match upon. If we've been asked to match over
775 // a QString, then subjectStorage is a copy of that string
776 // (so that it's kept alive by us)
779
782
783 // the capturedOffsets vector contains pairs of (start, end) positions
784 // for each captured substring
786
788
789 bool hasMatch = false;
790 bool hasPartialMatch = false;
791 bool isValid = false;
792};
793
795{
796 QRegularExpressionMatchIteratorPrivate(const QRegularExpression &re,
797 QRegularExpression::MatchType matchType,
798 QRegularExpression::MatchOptions matchOptions,
799 const QRegularExpressionMatch &next);
800
801 bool hasNext() const;
802 QRegularExpressionMatch next;
803 const QRegularExpression regularExpression;
806};
807
808/*!
809 \internal
810
811 Used to centralize the warning about using an invalid QRegularExpression.
812 In case the pattern is an illegal UTF-16 string, we can't pass print it
813 (pass it to qUtf16Printable, etc.), so we need to check for that.
814*/
816void qtWarnAboutInvalidRegularExpression(const QString &pattern, const char *cls, const char *method)
817{
818 if (pattern.isValidUtf16()) {
819 qWarning("%s::%s(): called on an invalid QRegularExpression object "
820 "(pattern is '%ls')", cls, method, qUtf16Printable(pattern));
821 } else {
822 qWarning("%s::%s(): called on an invalid QRegularExpression object",
823 cls, method);
824 }
825}
826
827/*!
828 \internal
829*/
830QRegularExpression::QRegularExpression(QRegularExpressionPrivate &dd)
831 : d(&dd)
832{
833}
834
835/*!
836 \internal
837*/
839 : QSharedData(),
841 pattern(),
842 mutex(),
843 compiledPattern(nullptr),
844 errorCode(0),
845 errorOffset(-1),
847 usingCrLfNewlines(false),
848 isDirty(true)
849{
850}
851
852/*!
853 \internal
854*/
859
860/*!
861 \internal
862
863 Copies the private, which means copying only the pattern and the pattern
864 options. The compiledPattern pointer is NOT copied (we
865 do not own it any more), and in general all the members set when
866 compiling a pattern are set to default values. isDirty is set back to true
867 so that the pattern has to be recompiled again.
868*/
882
883/*!
884 \internal
885*/
887{
888 pcre2_code_free_16(compiledPattern);
889 compiledPattern = nullptr;
890 errorCode = 0;
891 errorOffset = -1;
892 capturingCount = 0;
893 usingCrLfNewlines = false;
894}
895
896/*!
897 \internal
898*/
900{
901 const QMutexLocker lock(&mutex);
902
903 if (!isDirty)
904 return;
905
906 isDirty = false;
908
909 int options = convertToPcreOptions(patternOptions);
910 options |= PCRE2_UTF;
911
912 PCRE2_SIZE patternErrorOffset;
913 compiledPattern = pcre2_compile_16(reinterpret_cast<PCRE2_SPTR16>(pattern.constData()),
914 pattern.size(),
915 options,
916 &errorCode,
917 &patternErrorOffset,
918 nullptr);
919
920 if (!compiledPattern) {
921 errorOffset = qsizetype(patternErrorOffset);
922 return;
923 } else {
924 // ignore whatever PCRE2 wrote into errorCode -- leave it to 0 to mean "no error"
925 errorCode = 0;
926 }
927
930}
931
932/*!
933 \internal
934*/
936{
937 Q_ASSERT(compiledPattern);
938
939 pcre2_pattern_info_16(compiledPattern, PCRE2_INFO_CAPTURECOUNT, &capturingCount);
940
941 // detect the settings for the newline
942 unsigned int patternNewlineSetting;
943 if (pcre2_pattern_info_16(compiledPattern, PCRE2_INFO_NEWLINE, &patternNewlineSetting) != 0) {
944 // no option was specified in the regexp, grab PCRE build defaults
945 pcre2_config_16(PCRE2_CONFIG_NEWLINE, &patternNewlineSetting);
946 }
947
948 usingCrLfNewlines = (patternNewlineSetting == PCRE2_NEWLINE_CRLF) ||
949 (patternNewlineSetting == PCRE2_NEWLINE_ANY) ||
950 (patternNewlineSetting == PCRE2_NEWLINE_ANYCRLF);
951
952 unsigned int hasJOptionChanged;
953 pcre2_pattern_info_16(compiledPattern, PCRE2_INFO_JCHANGED, &hasJOptionChanged);
954 if (Q_UNLIKELY(hasJOptionChanged)) {
955 qWarning("QRegularExpressionPrivate::getPatternInfo(): the pattern '%ls'\n is using the (?J) option; duplicate capturing group names are not supported by Qt",
956 qUtf16Printable(pattern));
957 }
958}
959
960
961/*
962 Simple "smartpointer" wrapper around a pcre2_jit_stack_16, to be used with
963 QThreadStorage.
964*/
965namespace {
966struct PcreJitStackFree
967{
968 void operator()(pcre2_jit_stack_16 *stack) const
969 {
970 if (stack)
971 pcre2_jit_stack_free_16(stack);
972 }
973};
974Q_CONSTINIT static thread_local std::unique_ptr<pcre2_jit_stack_16, PcreJitStackFree> jitStacks;
975}
976
977/*!
978 \internal
979*/
980static pcre2_jit_stack_16 *qtPcreCallback(void *)
981{
982 return jitStacks.get();
983}
984
985/*!
986 \internal
987*/
988static bool isJitEnabled()
989{
990 QByteArray jitEnvironment = qgetenv("QT_ENABLE_REGEXP_JIT");
991 if (!jitEnvironment.isEmpty()) {
992 bool ok;
993 int enableJit = jitEnvironment.toInt(&ok);
994 return ok ? (enableJit != 0) : true;
995 }
996
997#ifdef QT_DEBUG
998 return false;
999#elif defined(Q_OS_MACOS) && !defined(QT_BOOTSTRAPPED)
1000 return !qt_mac_runningUnderRosetta();
1001#else
1002 return true;
1003#endif
1004}
1005
1006/*!
1007 \internal
1008
1009 The purpose of the function is to call pcre2_jit_compile_16, which
1010 JIT-compiles the pattern.
1011
1012 It gets called when a pattern is recompiled by us (in compilePattern()),
1013 under mutex protection.
1014*/
1016{
1017 Q_ASSERT(compiledPattern);
1018
1019 static const bool enableJit = isJitEnabled();
1020
1021 if (!enableJit)
1022 return;
1023
1024 pcre2_jit_compile_16(compiledPattern, PCRE2_JIT_COMPLETE | PCRE2_JIT_PARTIAL_SOFT | PCRE2_JIT_PARTIAL_HARD);
1025}
1026
1027/*!
1028 \internal
1029
1030 Returns the capturing group number for the given name. Duplicated names for
1031 capturing groups are not supported.
1032*/
1033int QRegularExpressionPrivate::captureIndexForName(QAnyStringView name) const
1034{
1035 Q_ASSERT(!name.isEmpty());
1036
1037 if (!compiledPattern)
1038 return -1;
1039
1040 // See the other usages of pcre2_pattern_info_16 for more details about this
1041 PCRE2_SPTR16 *namedCapturingTable;
1042 unsigned int namedCapturingTableEntryCount;
1043 unsigned int namedCapturingTableEntrySize;
1044
1045 pcre2_pattern_info_16(compiledPattern, PCRE2_INFO_NAMETABLE, &namedCapturingTable);
1046 pcre2_pattern_info_16(compiledPattern, PCRE2_INFO_NAMECOUNT, &namedCapturingTableEntryCount);
1047 pcre2_pattern_info_16(compiledPattern, PCRE2_INFO_NAMEENTRYSIZE, &namedCapturingTableEntrySize);
1048
1049 for (unsigned int i = 0; i < namedCapturingTableEntryCount; ++i) {
1050 const auto currentNamedCapturingTableRow =
1051 reinterpret_cast<const char16_t *>(namedCapturingTable) + namedCapturingTableEntrySize * i;
1052
1053 if (name == (currentNamedCapturingTableRow + 1)) {
1054 const int index = *currentNamedCapturingTableRow;
1055 return index;
1056 }
1057 }
1058
1059 return -1;
1060}
1061
1062/*!
1063 \internal
1064
1065 This is a simple wrapper for pcre2_match_16 for handling the case in which the
1066 JIT runs out of memory. In that case, we allocate a thread-local JIT stack
1067 and re-run pcre2_match_16.
1068*/
1069static int safe_pcre2_match_16(const pcre2_code_16 *code,
1070 PCRE2_SPTR16 subject, qsizetype length,
1071 qsizetype startOffset, int options,
1072 pcre2_match_data_16 *matchData,
1073 pcre2_match_context_16 *matchContext)
1074{
1075 int result = pcre2_match_16(code, subject, length,
1076 startOffset, options, matchData, matchContext);
1077
1078 if (result == PCRE2_ERROR_JIT_STACKLIMIT && !jitStacks) {
1079 // The default JIT stack size in PCRE is 32K,
1080 // we allocate from 32K up to 512K.
1081 jitStacks.reset(pcre2_jit_stack_create_16(32 * 1024, 512 * 1024, NULL));
1082
1083 result = pcre2_match_16(code, subject, length,
1084 startOffset, options, matchData, matchContext);
1085 }
1086
1087 return result;
1088}
1089
1090/*!
1091 \internal
1092
1093 Performs a match on the subject string view held by \a priv. The
1094 match will be of type priv->matchType and using the options
1095 priv->matchOptions; the matching \a offset is relative the
1096 substring, and if negative, it's taken as an offset from the end of
1097 the substring.
1098
1099 It also advances a match if a previous result is given as \a
1100 previous. The subject string goes a Unicode validity check if
1101 \a checkSubjectString is CheckSubjectString and the match options don't
1102 include DontCheckSubjectStringMatchOption (PCRE doesn't like illegal
1103 UTF-16 sequences).
1104
1105 \a priv is modified to hold the results of the match.
1106
1107 Advancing a match is a tricky algorithm. If the previous match matched a
1108 non-empty string, we just do an ordinary match at the offset position.
1109
1110 If the previous match matched an empty string, then an anchored, non-empty
1111 match is attempted at the offset position. If that succeeds, then we got
1112 the next match and we can return it. Otherwise, we advance by 1 position
1113 (which can be one or two code units in UTF-16!) and reattempt a "normal"
1114 match. We also have the problem of detecting the current newline format: if
1115 the new advanced offset is pointing to the beginning of a CRLF sequence, we
1116 must advance over it.
1117*/
1119 qsizetype offset,
1120 CheckSubjectStringOption checkSubjectStringOption,
1121 const QRegularExpressionMatchPrivate *previous) const
1122{
1123 Q_ASSERT(priv);
1124 Q_ASSERT(priv != previous);
1125
1126 const qsizetype subjectLength = priv->subject.size();
1127
1128 if (offset < 0)
1129 offset += subjectLength;
1130
1131 if (offset < 0 || offset > subjectLength)
1132 return;
1133
1134 if (Q_UNLIKELY(!compiledPattern)) {
1135 qtWarnAboutInvalidRegularExpression(pattern, "QRegularExpressionPrivate", "doMatch");
1136 return;
1137 }
1138
1139 // skip doing the actual matching if NoMatch type was requested
1140 if (priv->matchType == QRegularExpression::NoMatch) {
1141 priv->isValid = true;
1142 return;
1143 }
1144
1145 int pcreOptions = convertToPcreOptions(priv->matchOptions);
1146
1147 if (priv->matchType == QRegularExpression::PartialPreferCompleteMatch)
1148 pcreOptions |= PCRE2_PARTIAL_SOFT;
1149 else if (priv->matchType == QRegularExpression::PartialPreferFirstMatch)
1150 pcreOptions |= PCRE2_PARTIAL_HARD;
1151
1152 if (checkSubjectStringOption == DontCheckSubjectString)
1153 pcreOptions |= PCRE2_NO_UTF_CHECK;
1154
1155 bool previousMatchWasEmpty = false;
1156 if (previous && previous->hasMatch &&
1157 (previous->capturedOffsets.at(0) == previous->capturedOffsets.at(1))) {
1158 previousMatchWasEmpty = true;
1159 }
1160
1161 pcre2_match_context_16 *matchContext = pcre2_match_context_create_16(nullptr);
1162 pcre2_jit_stack_assign_16(matchContext, &qtPcreCallback, nullptr);
1163 pcre2_match_data_16 *matchData = pcre2_match_data_create_from_pattern_16(compiledPattern, nullptr);
1164
1165 // PCRE does not accept a null pointer as subject string, even if
1166 // its length is zero. We however allow it in input: a QStringView
1167 // subject may have data == nullptr. In this case, to keep PCRE
1168 // happy, pass a pointer to a dummy character.
1169 const char16_t dummySubject = 0;
1170 const char16_t * const subjectUtf16 = [&]()
1171 {
1172 const auto subjectUtf16 = priv->subject.utf16();
1173 if (subjectUtf16)
1174 return subjectUtf16;
1175 Q_ASSERT(subjectLength == 0);
1176 return &dummySubject;
1177 }();
1178
1179 int result;
1180
1181 if (!previousMatchWasEmpty) {
1182 result = safe_pcre2_match_16(compiledPattern,
1183 reinterpret_cast<PCRE2_SPTR16>(subjectUtf16), subjectLength,
1184 offset, pcreOptions,
1185 matchData, matchContext);
1186 } else {
1187 result = safe_pcre2_match_16(compiledPattern,
1188 reinterpret_cast<PCRE2_SPTR16>(subjectUtf16), subjectLength,
1189 offset, pcreOptions | PCRE2_NOTEMPTY_ATSTART | PCRE2_ANCHORED,
1190 matchData, matchContext);
1191
1192 if (result == PCRE2_ERROR_NOMATCH) {
1193 ++offset;
1194
1196 && offset < subjectLength
1197 && subjectUtf16[offset - 1] == u'\r'
1198 && subjectUtf16[offset] == u'\n') {
1199 ++offset;
1200 } else if (offset < subjectLength
1201 && QChar::isLowSurrogate(subjectUtf16[offset])) {
1202 ++offset;
1203 }
1204
1205 result = safe_pcre2_match_16(compiledPattern,
1206 reinterpret_cast<PCRE2_SPTR16>(subjectUtf16), subjectLength,
1207 offset, pcreOptions,
1208 matchData, matchContext);
1209 }
1210 }
1211
1212#ifdef QREGULAREXPRESSION_DEBUG
1213 qDebug() << "Matching" << pattern << "against" << subject
1214 << "offset" << offset
1215 << priv->matchType << priv->matchOptions << previousMatchWasEmpty
1216 << "result" << result;
1217#endif
1218
1219 // result == 0 means not enough space in captureOffsets; should never happen
1220 Q_ASSERT(result != 0);
1221
1222 if (result > 0) {
1223 // full match
1224 priv->isValid = true;
1225 priv->hasMatch = true;
1226 priv->capturedCount = result;
1227 priv->capturedOffsets.resize(result * 2);
1228 } else {
1229 // no match, partial match or error
1230 priv->hasPartialMatch = (result == PCRE2_ERROR_PARTIAL);
1231 priv->isValid = (result == PCRE2_ERROR_NOMATCH || result == PCRE2_ERROR_PARTIAL);
1232
1233 if (result == PCRE2_ERROR_PARTIAL) {
1234 // partial match:
1235 // leave the start and end capture offsets (i.e. cap(0))
1236 priv->capturedCount = 1;
1237 priv->capturedOffsets.resize(2);
1238 } else {
1239 // no match or error
1240 priv->capturedCount = 0;
1241 priv->capturedOffsets.clear();
1242 }
1243 }
1244
1245 // copy the captured substrings offsets, if any
1246 if (priv->capturedCount) {
1247 PCRE2_SIZE *ovector = pcre2_get_ovector_pointer_16(matchData);
1248 qsizetype *const capturedOffsets = priv->capturedOffsets.data();
1249
1250 // We rely on the fact that capturing groups that did not
1251 // capture anything have offset -1, but PCRE technically
1252 // returns "PCRE2_UNSET". Test that out, better safe than
1253 // sorry...
1254 static_assert(qsizetype(PCRE2_UNSET) == qsizetype(-1), "Internal error: PCRE2 changed its API");
1255
1256 for (int i = 0; i < priv->capturedCount * 2; ++i)
1257 capturedOffsets[i] = qsizetype(ovector[i]);
1258
1259 // For partial matches, PCRE2 and PCRE1 differ in behavior when lookbehinds
1260 // are involved. PCRE2 reports the real begin of the match and the maximum
1261 // used lookbehind as distinct information; PCRE1 instead automatically
1262 // adjusted ovector[0] to include the maximum lookbehind.
1263 //
1264 // For instance, given the pattern "\bstring\b", and the subject "a str":
1265 // * PCRE1 reports partial, capturing " str"
1266 // * PCRE2 reports partial, capturing "str" with a lookbehind of 1
1267 //
1268 // To keep behavior, emulate PCRE1 here.
1269 // (Eventually, we could expose the lookbehind info in a future patch.)
1270 if (result == PCRE2_ERROR_PARTIAL) {
1271 unsigned int maximumLookBehind;
1272 pcre2_pattern_info_16(compiledPattern, PCRE2_INFO_MAXLOOKBEHIND, &maximumLookBehind);
1273 capturedOffsets[0] -= maximumLookBehind;
1274 }
1275 }
1276
1277 pcre2_match_data_free_16(matchData);
1278 pcre2_match_context_free_16(matchContext);
1279}
1280
1281/*!
1282 \internal
1283*/
1285 const QString &subjectStorage,
1286 QStringView subject,
1287 QRegularExpression::MatchType matchType,
1288 QRegularExpression::MatchOptions matchOptions)
1294{
1295}
1296
1297/*!
1298 \internal
1299*/
1300QRegularExpressionMatch QRegularExpressionMatchPrivate::nextMatch() const
1301{
1302 Q_ASSERT(isValid);
1303 Q_ASSERT(hasMatch || hasPartialMatch);
1304
1305 auto nextPrivate = new QRegularExpressionMatchPrivate(regularExpression,
1306 subjectStorage,
1307 subject,
1308 matchType,
1309 matchOptions);
1310
1311 // Note the DontCheckSubjectString passed for the check of the subject string:
1312 // if we're advancing a match on the same subject,
1313 // then that subject was already checked at least once (when this object
1314 // was created, or when the object that created this one was created, etc.)
1315 regularExpression.d->doMatch(nextPrivate,
1316 capturedOffsets.at(1),
1317 QRegularExpressionPrivate::DontCheckSubjectString,
1318 this);
1319 return QRegularExpressionMatch(*nextPrivate);
1320}
1321
1322/*!
1323 \internal
1324*/
1326 QRegularExpression::MatchType matchType,
1327 QRegularExpression::MatchOptions matchOptions,
1328 const QRegularExpressionMatch &next)
1329 : next(next),
1332{
1333}
1334
1335/*!
1336 \internal
1337*/
1339{
1340 return next.isValid() && (next.hasMatch() || next.hasPartialMatch());
1341}
1342
1343// PUBLIC API
1344
1345/*!
1346 Constructs a QRegularExpression object with an empty pattern and no pattern
1347 options.
1348
1349 \sa setPattern(), setPatternOptions()
1350*/
1351QRegularExpression::QRegularExpression()
1352 : d(new QRegularExpressionPrivate)
1353{
1354}
1355
1356/*!
1357 Constructs a QRegularExpression object using the given \a pattern as
1358 pattern and the \a options as the pattern options.
1359
1360 For the risks of using a \a pattern from an untrusted source, see
1361 \l{sec-con-QRegularExpression}{Security Considerations}.
1362
1363 \sa setPattern(), setPatternOptions()
1364*/
1365QRegularExpression::QRegularExpression(const QString &pattern, PatternOptions options)
1366 : d(new QRegularExpressionPrivate)
1367{
1368 d->pattern = pattern;
1369 d->patternOptions = options;
1370}
1371
1372/*!
1373 Constructs a QRegularExpression object as a copy of \a re.
1374
1375 \sa operator=()
1376*/
1377QRegularExpression::QRegularExpression(const QRegularExpression &re) noexcept = default;
1378
1379/*!
1380 \fn QRegularExpression::QRegularExpression(QRegularExpression &&re)
1381
1382 \since 6.1
1383
1384 Constructs a QRegularExpression object by moving from \a re.
1385
1386 Note that a moved-from QRegularExpression can only be destroyed or
1387 assigned to. The effect of calling other functions than the destructor
1388 or one of the assignment operators is undefined.
1389
1390 \sa operator=()
1391*/
1392
1393/*!
1394 Destroys the QRegularExpression object.
1395*/
1396QRegularExpression::~QRegularExpression()
1397{
1398}
1399
1400QT_DEFINE_QESDP_SPECIALIZATION_DTOR(QRegularExpressionPrivate)
1401
1402/*!
1403 Assigns the regular expression \a re to this object, and returns a reference
1404 to the copy. Both the pattern and the pattern options are copied.
1405*/
1406QRegularExpression &QRegularExpression::operator=(const QRegularExpression &re) noexcept = default;
1407
1408/*!
1409 \fn void QRegularExpression::swap(QRegularExpression &other)
1410 \memberswap{regular expression}
1411*/
1412
1413/*!
1414 Returns the pattern string of the regular expression.
1415
1416 \sa setPattern(), patternOptions()
1417*/
1418QString QRegularExpression::pattern() const
1419{
1420 return d->pattern;
1421}
1422
1423/*!
1424 Sets the pattern string of the regular expression to \a pattern. The
1425 pattern options are left unchanged.
1426
1427 For the risks of using a \a pattern from an untrusted source, see
1428 \l{sec-con-QRegularExpression}{Security Considerations}.
1429
1430 \sa pattern(), setPatternOptions()
1431*/
1432void QRegularExpression::setPattern(const QString &pattern)
1433{
1434 if (d->pattern == pattern)
1435 return;
1436 d.detach();
1437 d->isDirty = true;
1438 d->pattern = pattern;
1439}
1440
1441/*!
1442 Returns the pattern options for the regular expression.
1443
1444 \sa setPatternOptions(), pattern()
1445*/
1446QRegularExpression::PatternOptions QRegularExpression::patternOptions() const
1447{
1448 return d->patternOptions;
1449}
1450
1451/*!
1452 Sets the given \a options as the pattern options of the regular expression.
1453 The pattern string is left unchanged.
1454
1455 \sa patternOptions(), setPattern()
1456*/
1457void QRegularExpression::setPatternOptions(PatternOptions options)
1458{
1459 if (d->patternOptions == options)
1460 return;
1461 d.detach();
1462 d->isDirty = true;
1463 d->patternOptions = options;
1464}
1465
1466/*!
1467 Returns the number of capturing groups inside the pattern string,
1468 or -1 if the regular expression is not valid.
1469
1470 \note The implicit capturing group 0 is \e{not} included in the returned number.
1471
1472 \sa isValid()
1473*/
1474int QRegularExpression::captureCount() const
1475{
1476 if (!isValid()) // will compile the pattern
1477 return -1;
1478 return d->capturingCount;
1479}
1480
1481/*!
1482 \since 5.1
1483
1484 Returns a list of captureCount() + 1 elements, containing the names of the
1485 named capturing groups in the pattern string. The list is sorted such that
1486 the element of the list at position \c{i} is the name of the \c{i}-th
1487 capturing group, if it has a name, or an empty string if that capturing
1488 group is unnamed.
1489
1490 For instance, given the regular expression
1491
1492 \snippet code/src_corelib_text_qregularexpression.cpp 32
1493
1494 namedCaptureGroups() will return the following list:
1495
1496 \snippet code/src_corelib_text_qregularexpression.cpp 33
1497
1498 which corresponds to the fact that the capturing group #0 (corresponding to
1499 the whole match) has no name, the capturing group #1 has name "day", the
1500 capturing group #2 has name "month", etc.
1501
1502 If the regular expression is not valid, returns an empty list.
1503
1504 \sa isValid(), QRegularExpressionMatch::captured(), QString::isEmpty()
1505*/
1506QStringList QRegularExpression::namedCaptureGroups() const
1507{
1508 if (!isValid()) // isValid() will compile the pattern
1509 return QStringList();
1510
1511 // namedCapturingTable will point to a table of
1512 // namedCapturingTableEntryCount entries, each one of which
1513 // contains one ushort followed by the name, NUL terminated.
1514 // The ushort is the numerical index of the name in the pattern.
1515 // The length of each entry is namedCapturingTableEntrySize.
1516 PCRE2_SPTR16 *namedCapturingTable;
1517 unsigned int namedCapturingTableEntryCount;
1518 unsigned int namedCapturingTableEntrySize;
1519
1520 pcre2_pattern_info_16(d->compiledPattern, PCRE2_INFO_NAMETABLE, &namedCapturingTable);
1521 pcre2_pattern_info_16(d->compiledPattern, PCRE2_INFO_NAMECOUNT, &namedCapturingTableEntryCount);
1522 pcre2_pattern_info_16(d->compiledPattern, PCRE2_INFO_NAMEENTRYSIZE, &namedCapturingTableEntrySize);
1523
1524 // The +1 is for the implicit group #0
1525 QStringList result(d->capturingCount + 1);
1526
1527 for (unsigned int i = 0; i < namedCapturingTableEntryCount; ++i) {
1528 const auto currentNamedCapturingTableRow =
1529 reinterpret_cast<const char16_t *>(namedCapturingTable) + namedCapturingTableEntrySize * i;
1530
1531 const int index = *currentNamedCapturingTableRow;
1532 result[index] = QStringView(currentNamedCapturingTableRow + 1).toString();
1533 }
1534
1535 return result;
1536}
1537
1538/*!
1539 Returns \c true if the regular expression is a valid regular expression (that
1540 is, it contains no syntax errors, etc.), or false otherwise. Use
1541 errorString() to obtain a textual description of the error.
1542
1543 \sa errorString(), patternErrorOffset()
1544*/
1545bool QRegularExpression::isValid() const
1546{
1547 d.data()->compilePattern();
1548 return d->compiledPattern;
1549}
1550
1551/*!
1552 Returns a textual description of the error found when checking the validity
1553 of the regular expression, or "no error" if no error was found.
1554
1555 \sa isValid(), patternErrorOffset()
1556*/
1557QString QRegularExpression::errorString() const
1558{
1559 d.data()->compilePattern();
1560 if (d->errorCode) {
1561 QString errorString;
1562 int errorStringLength;
1563 do {
1564 errorString.resize(errorString.size() + 64);
1565 errorStringLength = pcre2_get_error_message_16(d->errorCode,
1566 reinterpret_cast<ushort *>(errorString.data()),
1567 errorString.size());
1568 } while (errorStringLength < 0);
1569 errorString.resize(errorStringLength);
1570
1571#ifdef QT_NO_TRANSLATION
1572 return errorString;
1573#else
1574 return QCoreApplication::translate("QRegularExpression", std::move(errorString).toLatin1().constData());
1575#endif
1576 }
1577#ifdef QT_NO_TRANSLATION
1578 return u"no error"_s;
1579#else
1580 return QCoreApplication::translate("QRegularExpression", "no error");
1581#endif
1582}
1583
1584/*!
1585 Returns the offset, inside the pattern string, at which an error was found
1586 when checking the validity of the regular expression. If no error was
1587 found, then -1 is returned.
1588
1589 \sa pattern(), isValid(), errorString()
1590*/
1591qsizetype QRegularExpression::patternErrorOffset() const
1592{
1593 d.data()->compilePattern();
1594 return d->errorOffset;
1595}
1596
1597/*!
1598 Attempts to match the regular expression against the given \a subject
1599 string, starting at the position \a offset inside the subject, using a
1600 match of type \a matchType and honoring the given \a matchOptions.
1601
1602 The returned QRegularExpressionMatch object contains the results of the
1603 match.
1604
1605 \sa QRegularExpressionMatch, {normal matching}
1606*/
1607QRegularExpressionMatch QRegularExpression::match(const QString &subject,
1608 qsizetype offset,
1609 MatchType matchType,
1610 MatchOptions matchOptions) const
1611{
1612 d.data()->compilePattern();
1613 auto priv = new QRegularExpressionMatchPrivate(*this,
1614 subject,
1615 QStringView(subject),
1616 matchType,
1617 matchOptions);
1618 d->doMatch(priv, offset);
1619 return QRegularExpressionMatch(*priv);
1620}
1621
1622#if QT_DEPRECATED_SINCE(6, 8)
1623/*!
1624 \since 6.0
1625 \overload
1626 \deprecated [6.8]
1627
1628 Use matchView() instead.
1629*/
1630QRegularExpressionMatch QRegularExpression::match(QStringView subjectView,
1631 qsizetype offset,
1632 MatchType matchType,
1633 MatchOptions matchOptions) const
1634{
1635 return matchView(subjectView, offset, matchType, matchOptions);
1636}
1637#endif // QT_DEPRECATED_SINCE(6, 8)
1638
1639/*!
1640 \since 6.5
1641 \overload
1642
1643 Attempts to match the regular expression against the given \a subjectView
1644 string view, starting at the position \a offset inside the subject, using a
1645 match of type \a matchType and honoring the given \a matchOptions.
1646
1647 The returned QRegularExpressionMatch object contains the results of the
1648 match.
1649
1650 \note The data referenced by \a subjectView must remain valid as long
1651 as there are QRegularExpressionMatch objects using it.
1652
1653 \sa QRegularExpressionMatch, {normal matching}
1654*/
1655QRegularExpressionMatch QRegularExpression::matchView(QStringView subjectView,
1656 qsizetype offset,
1657 MatchType matchType,
1658 MatchOptions matchOptions) const
1659{
1660 d.data()->compilePattern();
1661 auto priv = new QRegularExpressionMatchPrivate(*this,
1662 QString(),
1663 subjectView,
1664 matchType,
1665 matchOptions);
1666 d->doMatch(priv, offset);
1667 return QRegularExpressionMatch(*priv);
1668}
1669
1670/*!
1671 Attempts to perform a global match of the regular expression against the
1672 given \a subject string, starting at the position \a offset inside the
1673 subject, using a match of type \a matchType and honoring the given \a
1674 matchOptions.
1675
1676 The returned QRegularExpressionMatchIterator is positioned before the
1677 first match result (if any).
1678
1679 \sa QRegularExpressionMatchIterator, {global matching}
1680*/
1681QRegularExpressionMatchIterator QRegularExpression::globalMatch(const QString &subject,
1682 qsizetype offset,
1683 MatchType matchType,
1684 MatchOptions matchOptions) const
1685{
1686 QRegularExpressionMatchIteratorPrivate *priv =
1687 new QRegularExpressionMatchIteratorPrivate(*this,
1688 matchType,
1689 matchOptions,
1690 match(subject, offset, matchType, matchOptions));
1691
1692 return QRegularExpressionMatchIterator(*priv);
1693}
1694
1695#if QT_DEPRECATED_SINCE(6, 8)
1696/*!
1697 \since 6.0
1698 \overload
1699 \deprecated [6.8]
1700
1701 Use globalMatchView() instead.
1702*/
1703QRegularExpressionMatchIterator QRegularExpression::globalMatch(QStringView subjectView,
1704 qsizetype offset,
1705 MatchType matchType,
1706 MatchOptions matchOptions) const
1707{
1708 return globalMatchView(subjectView, offset, matchType, matchOptions);
1709}
1710#endif // QT_DEPRECATED_SINCE(6, 8)
1711
1712/*!
1713 \since 6.5
1714 \overload
1715
1716 Attempts to perform a global match of the regular expression against the
1717 given \a subjectView string view, starting at the position \a offset inside the
1718 subject, using a match of type \a matchType and honoring the given \a
1719 matchOptions.
1720
1721 The returned QRegularExpressionMatchIterator is positioned before the
1722 first match result (if any).
1723
1724 \note The data referenced by \a subjectView must remain valid as
1725 long as there are QRegularExpressionMatchIterator or
1726 QRegularExpressionMatch objects using it.
1727
1728 \sa QRegularExpressionMatchIterator, {global matching}
1729*/
1730QRegularExpressionMatchIterator QRegularExpression::globalMatchView(QStringView subjectView,
1731 qsizetype offset,
1732 MatchType matchType,
1733 MatchOptions matchOptions) const
1734{
1735 QRegularExpressionMatchIteratorPrivate *priv =
1736 new QRegularExpressionMatchIteratorPrivate(*this,
1737 matchType,
1738 matchOptions,
1739 matchView(subjectView, offset, matchType, matchOptions));
1740
1741 return QRegularExpressionMatchIterator(*priv);
1742}
1743
1744/*!
1745 \since 5.4
1746
1747 Compiles the pattern immediately, including JIT compiling it (if
1748 the JIT is enabled) for optimization.
1749
1750 \sa isValid(), {Debugging Code that Uses QRegularExpression}
1751*/
1752void QRegularExpression::optimize() const
1753{
1754 d.data()->compilePattern();
1755}
1756
1757/*!
1758 \fn bool QRegularExpression::operator==(const QRegularExpression &lhs, const QRegularExpression &rhs) noexcept
1759
1760 Returns \c true if the \a lhs regular expression is equal to the \a rhs, or false
1761 otherwise. Two QRegularExpression objects are equal if they have
1762 the same pattern string and the same pattern options.
1763
1764 \sa operator!=()
1765*/
1766bool comparesEqual(const QRegularExpression &lhs,
1767 const QRegularExpression &rhs) noexcept
1768{
1769 return (lhs.d == rhs.d) ||
1770 (lhs.d->pattern == rhs.d->pattern && lhs.d->patternOptions == rhs.d->patternOptions);
1771}
1772/*!
1773 \fn QRegularExpression & QRegularExpression::operator=(QRegularExpression && re)
1774
1775 Move-assigns the regular expression \a re to this object, and returns a
1776 reference to the result. Both the pattern and the pattern options are copied.
1777
1778 Note that a moved-from QRegularExpression can only be destroyed or
1779 assigned to. The effect of calling other functions than the destructor
1780 or one of the assignment operators is undefined.
1781*/
1782
1783/*!
1784 \fn bool QRegularExpression::operator!=(const QRegularExpression &lhs, const QRegularExpression &rhs) noexcept
1785
1786 Returns \c true if the \a lhs regular expression is different from the \a rhs, or
1787 false otherwise.
1788
1789 \sa operator==()
1790*/
1791
1792/*!
1793 \since 5.6
1794 \relates QRegularExpression
1795
1796 Returns the hash value for \a key, using
1797 \a seed to seed the calculation.
1798*/
1799size_t qHash(const QRegularExpression &key, size_t seed) noexcept
1800{
1801 return qHashMulti(seed, key.d->pattern, key.d->patternOptions);
1802}
1803
1804/*!
1805 \fn QString QRegularExpression::escape(const QString &str)
1806 \overload
1807*/
1808
1809/*!
1810 \since 5.15
1811
1812 Escapes all characters of \a str so that they no longer have any special
1813 meaning when used as a regular expression pattern string, and returns
1814 the escaped string. For instance:
1815
1816 \snippet code/src_corelib_text_qregularexpression.cpp 26
1817
1818 This is very convenient in order to build patterns from arbitrary strings:
1819
1820 \snippet code/src_corelib_text_qregularexpression.cpp 27
1821
1822 \note This function implements Perl's quotemeta algorithm and escapes with
1823 a backslash all characters in \a str, except for the characters in the
1824 \c{[A-Z]}, \c{[a-z]} and \c{[0-9]} ranges, as well as the underscore
1825 (\c{_}) character. The only difference with Perl is that a literal NUL
1826 inside \a str is escaped with the sequence \c{"\\0"} (backslash +
1827 \c{'0'}), instead of \c{"\\\0"} (backslash + \c{NUL}).
1828*/
1829QString QRegularExpression::escape(QStringView str)
1830{
1831 QString result;
1832 const qsizetype count = str.size();
1833 result.reserve(count * 2);
1834
1835 // everything but [a-zA-Z0-9_] gets escaped,
1836 // cf. perldoc -f quotemeta
1837 for (qsizetype i = 0; i < count; ++i) {
1838 const QChar current = str.at(i);
1839
1840 if (current == QChar::Null) {
1841 // unlike Perl, a literal NUL must be escaped with
1842 // "\\0" (backslash + 0) and not "\\\0" (backslash + NUL),
1843 // because pcre16_compile uses a NUL-terminated string
1844 result.append(u'\\');
1845 result.append(u'0');
1846 } else if ((current < u'a' || current > u'z') &&
1847 (current < u'A' || current > u'Z') &&
1848 (current < u'0' || current > u'9') &&
1849 current != u'_') {
1850 result.append(u'\\');
1851 result.append(current);
1852 if (current.isHighSurrogate() && i < (count - 1))
1853 result.append(str.at(++i));
1854 } else {
1855 result.append(current);
1856 }
1857 }
1858
1859 result.squeeze();
1860 return result;
1861}
1862
1863/*!
1864 \since 5.12
1865 \fn QString QRegularExpression::wildcardToRegularExpression(const QString &pattern, WildcardConversionOptions options)
1866 \overload
1867*/
1868
1869/*!
1870 \since 6.0
1871 \enum QRegularExpression::WildcardConversionOption
1872
1873 The WildcardConversionOption enum defines modifiers to the way a wildcard glob
1874 pattern gets converted to a regular expression pattern.
1875
1876 \value DefaultWildcardConversion
1877 No conversion options are set.
1878
1879 \value UnanchoredWildcardConversion
1880 The conversion will not anchor the pattern. This allows for partial string matches of
1881 wildcard expressions.
1882
1883 \value [since 6.6] NonPathWildcardConversion
1884 The conversion will \e{not} interpret the pattern as filepath globbing.
1885
1886 \sa QRegularExpression::wildcardToRegularExpression
1887*/
1888
1889/*!
1890 \since 5.15
1891
1892 Returns a regular expression representation of the given glob \a pattern.
1893
1894 There are two transformations possible, one that targets file path
1895 globbing, and another one which is more generic.
1896
1897 By default, the transformation is targeting file path globbing,
1898 which means in particular that path separators receive special
1899 treatment. This implies that it is not just a basic translation
1900 from "*" to ".*" and similar.
1901
1902 \snippet code/src_corelib_text_qregularexpression.cpp 31
1903
1904 The more generic globbing transformation is available by passing
1905 \c NonPathWildcardConversion in the conversion \a options.
1906
1907 This implementation follows closely the definition
1908 of wildcard for glob patterns:
1909 \table
1910 \row \li \b{c}
1911 \li Any character represents itself apart from those mentioned
1912 below. Thus \b{c} matches the character \e c.
1913 \row \li \b{?}
1914 \li Matches any single character, except for a path separator
1915 (in case file path globbing has been selected). It is the
1916 same as b{.} in full regexps.
1917 \row \li \b{*}
1918 \li Matches zero or more of any characters, except for path
1919 separators (in case file path globbing has been selected). It is the
1920 same as \b{.*} in full regexps.
1921 \row \li \b{[abc]}
1922 \li Matches one character given in the bracket.
1923 \row \li \b{[a-c]}
1924 \li Matches one character from the range given in the bracket.
1925 \row \li \b{[!abc]}
1926 \li Matches one character that is not given in the bracket. It is the
1927 same as \b{[^abc]} in full regexp.
1928 \row \li \b{[!a-c]}
1929 \li Matches one character that is not from the range given in the
1930 bracket. It is the same as \b{[^a-c]} in full regexp.
1931 \endtable
1932
1933 \note For historical reasons, a backslash (\\‍) character is \e not
1934 an escape char in this context. In order to match one of the
1935 special characters, place it in square brackets (for example,
1936 \c{[?]}).
1937
1938 More information about the implementation can be found in:
1939 \list
1940 \li \l {https://en.wikipedia.org/wiki/Glob_(programming)} {The Wikipedia Glob article}
1941 \li \c {man 7 glob}
1942 \endlist
1943
1944 By default, the returned regular expression is fully anchored. In other
1945 words, there is no need of calling anchoredPattern() again on the
1946 result. To get a regular expression that is not anchored, pass
1947 UnanchoredWildcardConversion in the conversion \a options.
1948
1949 \sa escape()
1950*/
1951QString QRegularExpression::wildcardToRegularExpression(QStringView pattern, WildcardConversionOptions options)
1952{
1953 const qsizetype wclen = pattern.size();
1954 QString rx;
1955 rx.reserve(wclen + wclen / 16);
1956 qsizetype i = 0;
1957 const QChar *wc = pattern.data();
1958
1959 struct GlobSettings {
1960 char16_t nativePathSeparator;
1961 QStringView starEscape;
1962 QStringView questionMarkEscape;
1963 };
1964
1965 const GlobSettings settings = [options]() {
1966 if (options.testFlag(NonPathWildcardConversion)) {
1967 return GlobSettings{ u'\0', u".*", u"." };
1968 } else {
1969#ifdef Q_OS_WIN
1970 return GlobSettings{ u'\\', u"[^/\\\\‍]*", u"[^/\\\\‍]" };
1971#else
1972 return GlobSettings{ u'/', u"[^/]*", u"[^/]" };
1973#endif
1974 }
1975 }();
1976
1977 // We want a dot to match everything (incl. newlines), so enable /s mode,
1978 // limited to the pattern string we're producing.
1979 rx += u"(?s:";
1980
1981 while (i < wclen) {
1982 const QChar c = wc[i++];
1983 switch (c.unicode()) {
1984 case '*':
1985 rx += settings.starEscape;
1986 // Coalesce sequences of *
1987 while (i < wclen && wc[i] == u'*')
1988 ++i;
1989 break;
1990 case '?':
1991 rx += settings.questionMarkEscape;
1992 break;
1993 // When not using filepath globbing: \ is escaped, / is itself
1994 // When using filepath globbing:
1995 // * Unix: \ gets escaped. / is itself
1996 // * Windows: \ and / can match each other -- they become [/\\‍] in regexp
1997 case '\\':
1998#ifdef Q_OS_WIN
1999 if (options.testFlag(NonPathWildcardConversion))
2000 rx += u"\\\\";
2001 else
2002 rx += u"[/\\\\‍]";
2003 break;
2004 case '/':
2005 if (options.testFlag(NonPathWildcardConversion))
2006 rx += u'/';
2007 else
2008 rx += u"[/\\\\‍]";
2009 break;
2010#endif
2011 case '$':
2012 case '(':
2013 case ')':
2014 case '+':
2015 case '.':
2016 case '^':
2017 case '{':
2018 case '|':
2019 case '}':
2020 rx += u'\\';
2021 rx += c;
2022 break;
2023 case '[':
2024 rx += c;
2025 // Support for the [!abc] or [!a-c] syntax
2026 if (i < wclen) {
2027 if (wc[i] == u'!') {
2028 rx += u'^';
2029 ++i;
2030 }
2031
2032 if (i < wclen && wc[i] == u']')
2033 rx += wc[i++];
2034
2035 while (i < wclen && wc[i] != u']') {
2036 if (!options.testFlag(NonPathWildcardConversion)) {
2037 // The '/' appearing in a character class invalidates the
2038 // regular expression parsing. It also concerns '\\' on
2039 // Windows OS types.
2040 if (wc[i] == u'/' || wc[i] == settings.nativePathSeparator)
2041 return rx;
2042 }
2043 if (wc[i] == u'\\')
2044 rx += u'\\';
2045 rx += wc[i++];
2046 }
2047 }
2048 break;
2049 default:
2050 rx += c;
2051 break;
2052 }
2053 }
2054
2055 // Closes the (?s: group opened above
2056 rx += u")";
2057
2058 if (!(options & UnanchoredWildcardConversion))
2059 rx = anchoredPattern(rx);
2060
2061 return rx;
2062}
2063
2064/*!
2065 \since 6.0
2066 Returns a regular expression of the glob pattern \a pattern. The regular expression
2067 will be case sensitive if \a cs is \l{Qt::CaseSensitive}, and converted according to
2068 \a options.
2069
2070 Equivalent to
2071 \code
2072 auto reOptions = cs == Qt::CaseSensitive ? QRegularExpression::NoPatternOption :
2073 QRegularExpression::CaseInsensitiveOption;
2074 return QRegularExpression(wildcardToRegularExpression(str, options), reOptions);
2075 \endcode
2076*/
2077QRegularExpression QRegularExpression::fromWildcard(QStringView pattern, Qt::CaseSensitivity cs,
2078 WildcardConversionOptions options)
2079{
2080 auto reOptions = cs == Qt::CaseSensitive ? QRegularExpression::NoPatternOption :
2081 QRegularExpression::CaseInsensitiveOption;
2082 return QRegularExpression(wildcardToRegularExpression(pattern, options), reOptions);
2083}
2084
2085/*!
2086 \fn QRegularExpression::anchoredPattern(const QString &expression)
2087 \since 5.12
2088 \overload
2089*/
2090
2091/*!
2092 \since 5.15
2093
2094 Returns the \a expression wrapped between the \c{\A} and \c{\z} anchors to
2095 be used for exact matching.
2096*/
2097QString QRegularExpression::anchoredPattern(QStringView expression)
2098{
2099 return QString()
2100 + "\\A(?:"_L1
2101 + expression
2102 + ")\\z"_L1;
2103}
2104
2105/*!
2106 \since 5.1
2107
2108 Constructs a valid, empty QRegularExpressionMatch object. The regular
2109 expression is set to a default-constructed one; the match type to
2110 QRegularExpression::NoMatch and the match options to
2111 QRegularExpression::NoMatchOption.
2112
2113 The object will report no match through the hasMatch() and the
2114 hasPartialMatch() member functions.
2115*/
2116QRegularExpressionMatch::QRegularExpressionMatch()
2117 : d(new QRegularExpressionMatchPrivate(QRegularExpression(),
2118 QString(),
2119 QStringView(),
2120 QRegularExpression::NoMatch,
2121 QRegularExpression::NoMatchOption))
2122{
2123 d->isValid = true;
2124}
2125
2126/*!
2127 Destroys the match result.
2128*/
2129QRegularExpressionMatch::~QRegularExpressionMatch()
2130{
2131}
2132
2133QT_DEFINE_QESDP_SPECIALIZATION_DTOR(QRegularExpressionMatchPrivate)
2134
2135/*!
2136 Constructs a match result by copying the result of the given \a match.
2137
2138 \sa operator=()
2139*/
2140QRegularExpressionMatch::QRegularExpressionMatch(const QRegularExpressionMatch &match)
2141 : d(match.d)
2142{
2143}
2144
2145/*!
2146 \fn QRegularExpressionMatch::QRegularExpressionMatch(QRegularExpressionMatch &&match)
2147
2148 \since 6.1
2149
2150 Constructs a match result by moving the result from the given \a match.
2151
2152 Note that a moved-from QRegularExpressionMatch can only be destroyed or
2153 assigned to. The effect of calling other functions than the destructor
2154 or one of the assignment operators is undefined.
2155
2156 \sa operator=()
2157*/
2158
2159/*!
2160 Assigns the match result \a match to this object, and returns a reference
2161 to the copy.
2162*/
2163QRegularExpressionMatch &QRegularExpressionMatch::operator=(const QRegularExpressionMatch &match)
2164{
2165 d = match.d;
2166 return *this;
2167}
2168
2169/*!
2170 \fn QRegularExpressionMatch &QRegularExpressionMatch::operator=(QRegularExpressionMatch &&match)
2171
2172 Move-assigns the match result \a match to this object, and returns a
2173 reference to the result.
2174
2175 Note that a moved-from QRegularExpressionMatch can only be destroyed or
2176 assigned to. The effect of calling other functions than the destructor
2177 or one of the assignment operators is undefined.
2178*/
2179
2180/*!
2181 \fn void QRegularExpressionMatch::swap(QRegularExpressionMatch &other)
2182 \memberswap{match result}
2183*/
2184
2185/*!
2186 \internal
2187*/
2188QRegularExpressionMatch::QRegularExpressionMatch(QRegularExpressionMatchPrivate &dd)
2189 : d(&dd)
2190{
2191}
2192
2193/*!
2194 Returns the QRegularExpression object whose match() function returned this
2195 object.
2196
2197 \sa QRegularExpression::match(), matchType(), matchOptions()
2198*/
2199QRegularExpression QRegularExpressionMatch::regularExpression() const
2200{
2201 return d->regularExpression;
2202}
2203
2204
2205/*!
2206 Returns the match type that was used to get this QRegularExpressionMatch
2207 object, that is, the match type that was passed to
2208 QRegularExpression::match() or QRegularExpression::globalMatch().
2209
2210 \sa QRegularExpression::match(), regularExpression(), matchOptions()
2211*/
2212QRegularExpression::MatchType QRegularExpressionMatch::matchType() const
2213{
2214 return d->matchType;
2215}
2216
2217/*!
2218 Returns the match options that were used to get this
2219 QRegularExpressionMatch object, that is, the match options that were passed
2220 to QRegularExpression::match() or QRegularExpression::globalMatch().
2221
2222 \sa QRegularExpression::match(), regularExpression(), matchType()
2223*/
2224QRegularExpression::MatchOptions QRegularExpressionMatch::matchOptions() const
2225{
2226 return d->matchOptions;
2227}
2228
2229/*!
2230 Returns the index of the last capturing group that captured something,
2231 including the implicit capturing group 0. This can be used to extract all
2232 the substrings that were captured:
2233
2234 \snippet code/src_corelib_text_qregularexpression.cpp 28
2235
2236 Note that some of the capturing groups with an index less than
2237 lastCapturedIndex() could have not matched, and therefore captured nothing.
2238
2239 If the regular expression did not match, this function returns -1.
2240
2241 \sa hasCaptured(), captured(), capturedStart(), capturedEnd(), capturedLength()
2242*/
2243int QRegularExpressionMatch::lastCapturedIndex() const
2244{
2245 return d->capturedCount - 1;
2246}
2247
2248/*!
2249 \fn bool QRegularExpressionMatch::hasCaptured(QAnyStringView name) const
2250 \since 6.3
2251
2252 Returns true if the capturing group named \a name captured something
2253 in the subject string, and false otherwise (or if there is no
2254 capturing group called \a name).
2255
2256 \note Some capturing groups in a regular expression may not have
2257 captured anything even if the regular expression matched. This may
2258 happen, for instance, if a conditional operator is used in the
2259 pattern:
2260
2261 \snippet code/src_corelib_text_qregularexpression.cpp 36
2262
2263 Similarly, a capturing group may capture a substring of length 0;
2264 this function will return \c{true} for such a capturing group.
2265
2266 \note In Qt versions prior to 6.8, this function took QString or
2267 QStringView, not QAnyStringView.
2268
2269 \sa captured(), hasMatch()
2270*/
2271bool QRegularExpressionMatch::hasCaptured(QAnyStringView name) const
2272{
2273 const int nth = d->regularExpression.d->captureIndexForName(name);
2274 return hasCaptured(nth);
2275}
2276
2277/*!
2278 \since 6.3
2279
2280 Returns true if the \a nth capturing group captured something
2281 in the subject string, and false otherwise (or if there is no
2282 such capturing group).
2283
2284 \note The implicit capturing group number 0 captures the substring
2285 matched by the entire pattern.
2286
2287 \note Some capturing groups in a regular expression may not have
2288 captured anything even if the regular expression matched. This may
2289 happen, for instance, if a conditional operator is used in the
2290 pattern:
2291
2292 \snippet code/src_corelib_text_qregularexpression.cpp 36
2293
2294 Similarly, a capturing group may capture a substring of length 0;
2295 this function will return \c{true} for such a capturing group.
2296
2297 \sa captured(), lastCapturedIndex(), hasMatch()
2298*/
2299bool QRegularExpressionMatch::hasCaptured(int nth) const
2300{
2301 if (nth < 0 || nth > lastCapturedIndex())
2302 return false;
2303
2304 return d->capturedOffsets.at(nth * 2) != -1;
2305}
2306
2307/*!
2308 Returns the substring captured by the \a nth capturing group.
2309
2310 If the \a nth capturing group did not capture a string, or if there is no
2311 such capturing group, returns a null QString.
2312
2313 \note The implicit capturing group number 0 captures the substring matched
2314 by the entire pattern.
2315
2316 \sa capturedView(), lastCapturedIndex(), capturedStart(), capturedEnd(),
2317 capturedLength(), QString::isNull()
2318*/
2319QString QRegularExpressionMatch::captured(int nth) const
2320{
2321 return capturedView(nth).toString();
2322}
2323
2324/*!
2325 \since 5.10
2326
2327 Returns a view of the substring captured by the \a nth capturing group.
2328
2329 If the \a nth capturing group did not capture a string, or if there is no
2330 such capturing group, returns a null QStringView.
2331
2332 \note The implicit capturing group number 0 captures the substring matched
2333 by the entire pattern.
2334
2335 \sa captured(), lastCapturedIndex(), capturedStart(), capturedEnd(),
2336 capturedLength(), QStringView::isNull()
2337*/
2338QStringView QRegularExpressionMatch::capturedView(int nth) const
2339{
2340 if (!hasCaptured(nth))
2341 return QStringView();
2342
2343 qsizetype start = capturedStart(nth);
2344
2345 if (start == -1) // didn't capture
2346 return QStringView();
2347
2348 return d->subject.mid(start, capturedLength(nth));
2349}
2350
2351/*!
2352 \since 5.10
2353
2354 Returns the substring captured by the capturing group named \a name.
2355
2356 If the named capturing group \a name did not capture a string, or if
2357 there is no capturing group named \a name, returns a null QString.
2358
2359 \note In Qt versions prior to 6.8, this function took QString or
2360 QStringView, not QAnyStringView.
2361
2362 \sa capturedView(), capturedStart(), capturedEnd(), capturedLength(),
2363 QString::isNull()
2364*/
2365QString QRegularExpressionMatch::captured(QAnyStringView name) const
2366{
2367 if (name.isEmpty()) {
2368 qWarning("QRegularExpressionMatch::captured: empty capturing group name passed");
2369 return QString();
2370 }
2371
2372 return capturedView(name).toString();
2373}
2374
2375/*!
2376 \since 5.10
2377
2378 Returns a view of the string captured by the capturing group named \a
2379 name.
2380
2381 If the named capturing group \a name did not capture a string, or if
2382 there is no capturing group named \a name, returns a null QStringView.
2383
2384 \note In Qt versions prior to 6.8, this function took QString or
2385 QStringView, not QAnyStringView.
2386
2387 \sa captured(), capturedStart(), capturedEnd(), capturedLength(),
2388 QStringView::isNull()
2389*/
2390QStringView QRegularExpressionMatch::capturedView(QAnyStringView name) const
2391{
2392 if (name.isEmpty()) {
2393 qWarning("QRegularExpressionMatch::capturedView: empty capturing group name passed");
2394 return QStringView();
2395 }
2396 int nth = d->regularExpression.d->captureIndexForName(name);
2397 if (nth == -1)
2398 return QStringView();
2399 return capturedView(nth);
2400}
2401
2402/*!
2403 Returns a list of all strings captured by capturing groups, in the order
2404 the groups themselves appear in the pattern string. The list includes the
2405 implicit capturing group number 0, capturing the substring matched by the
2406 entire pattern.
2407*/
2408QStringList QRegularExpressionMatch::capturedTexts() const
2409{
2410 QStringList texts;
2411 texts.reserve(d->capturedCount);
2412 for (int i = 0; i < d->capturedCount; ++i)
2413 texts << captured(i);
2414 return texts;
2415}
2416
2417/*!
2418 Returns the offset inside the subject string corresponding to the
2419 starting position of the substring captured by the \a nth capturing group.
2420 If the \a nth capturing group did not capture a string or doesn't exist,
2421 returns -1.
2422
2423 \sa capturedEnd(), capturedLength(), captured()
2424*/
2425qsizetype QRegularExpressionMatch::capturedStart(int nth) const
2426{
2427 if (!hasCaptured(nth))
2428 return -1;
2429
2430 return d->capturedOffsets.at(nth * 2);
2431}
2432
2433/*!
2434 Returns the length of the substring captured by the \a nth capturing group.
2435
2436 \note This function returns 0 if the \a nth capturing group did not capture
2437 a string or doesn't exist.
2438
2439 \sa capturedStart(), capturedEnd(), captured()
2440*/
2441qsizetype QRegularExpressionMatch::capturedLength(int nth) const
2442{
2443 // bound checking performed by these two functions
2444 return capturedEnd(nth) - capturedStart(nth);
2445}
2446
2447/*!
2448 Returns the offset inside the subject string immediately after the ending
2449 position of the substring captured by the \a nth capturing group. If the \a
2450 nth capturing group did not capture a string or doesn't exist, returns -1.
2451
2452 \sa capturedStart(), capturedLength(), captured()
2453*/
2454qsizetype QRegularExpressionMatch::capturedEnd(int nth) const
2455{
2456 if (!hasCaptured(nth))
2457 return -1;
2458
2459 return d->capturedOffsets.at(nth * 2 + 1);
2460}
2461
2462/*!
2463 \since 5.10
2464
2465 Returns the offset inside the subject string corresponding to the starting
2466 position of the substring captured by the capturing group named \a name.
2467 If the capturing group named \a name did not capture a string or doesn't
2468 exist, returns -1.
2469
2470 \note In Qt versions prior to 6.8, this function took QString or
2471 QStringView, not QAnyStringView.
2472
2473 \sa capturedEnd(), capturedLength(), captured()
2474*/
2475qsizetype QRegularExpressionMatch::capturedStart(QAnyStringView name) const
2476{
2477 if (name.isEmpty()) {
2478 qWarning("QRegularExpressionMatch::capturedStart: empty capturing group name passed");
2479 return -1;
2480 }
2481 int nth = d->regularExpression.d->captureIndexForName(name);
2482 if (nth == -1)
2483 return -1;
2484 return capturedStart(nth);
2485}
2486
2487/*!
2488 \since 5.10
2489
2490 Returns the length of the substring captured by the capturing group named
2491 \a name.
2492
2493 \note This function returns 0 if the capturing group named \a name did not
2494 capture a string or doesn't exist.
2495
2496 \note In Qt versions prior to 6.8, this function took QString or
2497 QStringView, not QAnyStringView.
2498
2499 \sa capturedStart(), capturedEnd(), captured()
2500*/
2501qsizetype QRegularExpressionMatch::capturedLength(QAnyStringView name) const
2502{
2503 if (name.isEmpty()) {
2504 qWarning("QRegularExpressionMatch::capturedLength: empty capturing group name passed");
2505 return 0;
2506 }
2507 int nth = d->regularExpression.d->captureIndexForName(name);
2508 if (nth == -1)
2509 return 0;
2510 return capturedLength(nth);
2511}
2512
2513/*!
2514 \since 5.10
2515
2516 Returns the offset inside the subject string immediately after the ending
2517 position of the substring captured by the capturing group named \a name. If
2518 the capturing group named \a name did not capture a string or doesn't
2519 exist, returns -1.
2520
2521 \note In Qt versions prior to 6.8, this function took QString or
2522 QStringView, not QAnyStringView.
2523
2524 \sa capturedStart(), capturedLength(), captured()
2525*/
2526qsizetype QRegularExpressionMatch::capturedEnd(QAnyStringView name) const
2527{
2528 if (name.isEmpty()) {
2529 qWarning("QRegularExpressionMatch::capturedEnd: empty capturing group name passed");
2530 return -1;
2531 }
2532 int nth = d->regularExpression.d->captureIndexForName(name);
2533 if (nth == -1)
2534 return -1;
2535 return capturedEnd(nth);
2536}
2537
2538/*!
2539 Returns \c true if the regular expression matched against the subject string,
2540 or false otherwise.
2541
2542 \sa QRegularExpression::match(), hasPartialMatch()
2543*/
2544bool QRegularExpressionMatch::hasMatch() const
2545{
2546 return d->hasMatch;
2547}
2548
2549/*!
2550 Returns \c true if the regular expression partially matched against the
2551 subject string, or false otherwise.
2552
2553 \note Only a match that explicitly used the one of the partial match types
2554 can yield a partial match. Still, if such a match succeeds totally, this
2555 function will return false, while hasMatch() will return true.
2556
2557 \sa QRegularExpression::match(), QRegularExpression::MatchType, hasMatch()
2558*/
2559bool QRegularExpressionMatch::hasPartialMatch() const
2560{
2561 return d->hasPartialMatch;
2562}
2563
2564/*!
2565 Returns \c true if the match object was obtained as a result from the
2566 QRegularExpression::match() function invoked on a valid QRegularExpression
2567 object; returns \c false if the QRegularExpression was invalid.
2568
2569 \sa QRegularExpression::match(), QRegularExpression::isValid()
2570*/
2571bool QRegularExpressionMatch::isValid() const
2572{
2573 return d->isValid;
2574}
2575
2576/*!
2577 \internal
2578*/
2579QRegularExpressionMatchIterator::QRegularExpressionMatchIterator(QRegularExpressionMatchIteratorPrivate &dd)
2580 : d(&dd)
2581{
2582}
2583
2584/*!
2585 \since 5.1
2586
2587 Constructs an empty, valid QRegularExpressionMatchIterator object. The
2588 regular expression is set to a default-constructed one; the match type to
2589 QRegularExpression::NoMatch and the match options to
2590 QRegularExpression::NoMatchOption.
2591
2592 Invoking the hasNext() member function on the constructed object will
2593 return false, as the iterator is not iterating on a valid sequence of
2594 matches.
2595*/
2596QRegularExpressionMatchIterator::QRegularExpressionMatchIterator()
2597 : d(new QRegularExpressionMatchIteratorPrivate(QRegularExpression(),
2598 QRegularExpression::NoMatch,
2599 QRegularExpression::NoMatchOption,
2600 QRegularExpressionMatch()))
2601{
2602}
2603
2604/*!
2605 Destroys the QRegularExpressionMatchIterator object.
2606*/
2607QRegularExpressionMatchIterator::~QRegularExpressionMatchIterator()
2608{
2609}
2610
2611QT_DEFINE_QESDP_SPECIALIZATION_DTOR(QRegularExpressionMatchIteratorPrivate)
2612
2613/*!
2614 Constructs a QRegularExpressionMatchIterator object as a copy of \a
2615 iterator.
2616
2617 \sa operator=()
2618*/
2619QRegularExpressionMatchIterator::QRegularExpressionMatchIterator(const QRegularExpressionMatchIterator &iterator)
2620 : d(iterator.d)
2621{
2622}
2623
2624/*!
2625 \fn QRegularExpressionMatchIterator::QRegularExpressionMatchIterator(QRegularExpressionMatchIterator &&iterator)
2626
2627 \since 6.1
2628
2629 Constructs a QRegularExpressionMatchIterator object by moving from \a iterator.
2630
2631 Note that a moved-from QRegularExpressionMatchIterator can only be destroyed
2632 or assigned to. The effect of calling other functions than the destructor
2633 or one of the assignment operators is undefined.
2634
2635 \sa operator=()
2636*/
2637
2638/*!
2639 Assigns the iterator \a iterator to this object, and returns a reference to
2640 the copy.
2641*/
2642QRegularExpressionMatchIterator &QRegularExpressionMatchIterator::operator=(const QRegularExpressionMatchIterator &iterator)
2643{
2644 d = iterator.d;
2645 return *this;
2646}
2647
2648/*!
2649 \fn QRegularExpressionMatchIterator &QRegularExpressionMatchIterator::operator=(QRegularExpressionMatchIterator &&iterator)
2650
2651 Move-assigns the \a iterator to this object, and returns a reference to the
2652 result.
2653
2654 Note that a moved-from QRegularExpressionMatchIterator can only be destroyed
2655 or assigned to. The effect of calling other functions than the destructor
2656 or one of the assignment operators is undefined.
2657*/
2658
2659/*!
2660 \fn void QRegularExpressionMatchIterator::swap(QRegularExpressionMatchIterator &other)
2661 \memberswap{iterator}
2662*/
2663
2664/*!
2665 Returns \c true if the iterator object was obtained as a result from the
2666 QRegularExpression::globalMatch() function invoked on a valid
2667 QRegularExpression object; returns \c false if the QRegularExpression was
2668 invalid.
2669
2670 \sa QRegularExpression::globalMatch(), QRegularExpression::isValid()
2671*/
2672bool QRegularExpressionMatchIterator::isValid() const
2673{
2674 return d->next.isValid();
2675}
2676
2677/*!
2678 Returns \c true if there is at least one match result ahead of the iterator;
2679 otherwise it returns \c false.
2680
2681 \sa next()
2682*/
2683bool QRegularExpressionMatchIterator::hasNext() const
2684{
2685 return d->hasNext();
2686}
2687
2688/*!
2689 Returns the next match result without moving the iterator.
2690
2691 \note Calling this function when the iterator is at the end of the result
2692 set leads to undefined results.
2693*/
2694QRegularExpressionMatch QRegularExpressionMatchIterator::peekNext() const
2695{
2696 if (!hasNext())
2697 qWarning("QRegularExpressionMatchIterator::peekNext() called on an iterator already at end");
2698
2699 return d->next;
2700}
2701
2702/*!
2703 Returns the next match result and advances the iterator by one position.
2704
2705 \note Calling this function when the iterator is at the end of the result
2706 set leads to undefined results.
2707*/
2708QRegularExpressionMatch QRegularExpressionMatchIterator::next()
2709{
2710 if (!hasNext()) {
2711 qWarning("QRegularExpressionMatchIterator::next() called on an iterator already at end");
2712 return d.constData()->next;
2713 }
2714
2715 d.detach();
2716 return std::exchange(d->next, d->next.d.constData()->nextMatch());
2717}
2718
2719/*!
2720 Returns the QRegularExpression object whose globalMatch() function returned
2721 this object.
2722
2723 \sa QRegularExpression::globalMatch(), matchType(), matchOptions()
2724*/
2725QRegularExpression QRegularExpressionMatchIterator::regularExpression() const
2726{
2727 return d->regularExpression;
2728}
2729
2730/*!
2731 Returns the match type that was used to get this
2732 QRegularExpressionMatchIterator object, that is, the match type that was
2733 passed to QRegularExpression::globalMatch().
2734
2735 \sa QRegularExpression::globalMatch(), regularExpression(), matchOptions()
2736*/
2737QRegularExpression::MatchType QRegularExpressionMatchIterator::matchType() const
2738{
2739 return d->matchType;
2740}
2741
2742/*!
2743 Returns the match options that were used to get this
2744 QRegularExpressionMatchIterator object, that is, the match options that
2745 were passed to QRegularExpression::globalMatch().
2746
2747 \sa QRegularExpression::globalMatch(), regularExpression(), matchType()
2748*/
2749QRegularExpression::MatchOptions QRegularExpressionMatchIterator::matchOptions() const
2750{
2751 return d->matchOptions;
2752}
2753
2754/*!
2755 \internal
2756*/
2761
2762/*!
2763 \fn QtPrivate::QRegularExpressionMatchIteratorRangeBasedForIteratorSentinel end(const QRegularExpressionMatchIterator &)
2764 \internal
2765*/
2766
2767#ifndef QT_NO_DATASTREAM
2768/*!
2769 \relates QRegularExpression
2770
2771 Writes the regular expression \a re to stream \a out.
2772
2773 \sa {Serializing Qt Data Types}
2774*/
2775QDataStream &operator<<(QDataStream &out, const QRegularExpression &re)
2776{
2777 out << re.pattern() << quint32(re.patternOptions().toInt());
2778 return out;
2779}
2780
2781/*!
2782 \relates QRegularExpression
2783
2784 Reads a regular expression from stream \a in into \a re.
2785
2786 The stream sets the pattern string of \a re. For the risks of reading a
2787 pattern from an untrusted source, see
2788 \l{sec-con-QRegularExpression}{Security Considerations}.
2789
2790 \sa {Serializing Qt Data Types}
2791*/
2792QDataStream &operator>>(QDataStream &in, QRegularExpression &re)
2793{
2794 QString pattern;
2795 quint32 patternOptions;
2796 in >> pattern >> patternOptions;
2797 re.setPattern(pattern);
2798 re.setPatternOptions(QRegularExpression::PatternOptions::fromInt(patternOptions));
2799 return in;
2800}
2801#endif
2802
2803#ifndef QT_NO_DEBUG_STREAM
2804/*!
2805 \relates QRegularExpression
2806
2807 Writes the regular expression \a re into the debug object \a debug for
2808 debugging purposes.
2809
2810 \sa {Debugging Techniques}
2811*/
2812QDebug operator<<(QDebug debug, const QRegularExpression &re)
2813{
2814 QDebugStateSaver saver(debug);
2815 debug.nospace() << "QRegularExpression(" << re.pattern() << ", " << re.patternOptions() << ')';
2816 return debug;
2817}
2818
2819/*!
2820 \relates QRegularExpression
2821
2822 Writes the pattern options \a patternOptions into the debug object \a debug
2823 for debugging purposes.
2824
2825 \sa {Debugging Techniques}
2826*/
2827QDebug operator<<(QDebug debug, QRegularExpression::PatternOptions patternOptions)
2828{
2829 QDebugStateSaver saver(debug);
2830 QByteArray flags;
2831
2832 if (patternOptions == QRegularExpression::NoPatternOption) {
2833 flags = "NoPatternOption";
2834 } else {
2835 flags.reserve(200); // worst case...
2836 if (patternOptions & QRegularExpression::CaseInsensitiveOption)
2837 flags.append("CaseInsensitiveOption|");
2838 if (patternOptions & QRegularExpression::DotMatchesEverythingOption)
2839 flags.append("DotMatchesEverythingOption|");
2840 if (patternOptions & QRegularExpression::MultilineOption)
2841 flags.append("MultilineOption|");
2842 if (patternOptions & QRegularExpression::ExtendedPatternSyntaxOption)
2843 flags.append("ExtendedPatternSyntaxOption|");
2844 if (patternOptions & QRegularExpression::InvertedGreedinessOption)
2845 flags.append("InvertedGreedinessOption|");
2846 if (patternOptions & QRegularExpression::DontCaptureOption)
2847 flags.append("DontCaptureOption|");
2848 if (patternOptions & QRegularExpression::UseUnicodePropertiesOption)
2849 flags.append("UseUnicodePropertiesOption|");
2850 flags.chop(1);
2851 }
2852
2853 debug.nospace() << "QRegularExpression::PatternOptions(" << flags << ')';
2854
2855 return debug;
2856}
2857/*!
2858 \relates QRegularExpressionMatch
2859
2860 Writes the match object \a match into the debug object \a debug for
2861 debugging purposes.
2862
2863 \sa {Debugging Techniques}
2864*/
2865QDebug operator<<(QDebug debug, const QRegularExpressionMatch &match)
2866{
2867 QDebugStateSaver saver(debug);
2868 debug.nospace() << "QRegularExpressionMatch(";
2869
2870 if (!match.isValid()) {
2871 debug << "Invalid)";
2872 return debug;
2873 }
2874
2875 debug << "Valid";
2876
2877 if (match.hasMatch()) {
2878 debug << ", has match: ";
2879 for (int i = 0; i <= match.lastCapturedIndex(); ++i) {
2880 debug << i
2881 << ":(" << match.capturedStart(i) << ", " << match.capturedEnd(i)
2882 << ", " << match.captured(i) << ')';
2883 if (i < match.lastCapturedIndex())
2884 debug << ", ";
2885 }
2886 } else if (match.hasPartialMatch()) {
2887 debug << ", has partial match: ("
2888 << match.capturedStart(0) << ", "
2889 << match.capturedEnd(0) << ", "
2890 << match.captured(0) << ')';
2891 } else {
2892 debug << ", no match";
2893 }
2894
2895 debug << ')';
2896
2897 return debug;
2898}
2899#endif
2900
2901// fool lupdate: make it extract those strings for translation, but don't put them
2902// inside Qt -- they're already inside libpcre (cf. man 3 pcreapi, pcre_compile.c).
2903#if 0
2904
2905/* PCRE is a library of functions to support regular expressions whose syntax
2906and semantics are as close as possible to those of the Perl 5 language.
2907
2908 Written by Philip Hazel
2909 Original API code Copyright (c) 1997-2012 University of Cambridge
2910 New API code Copyright (c) 2015 University of Cambridge
2911
2912-----------------------------------------------------------------------------
2913Redistribution and use in source and binary forms, with or without
2914modification, are permitted provided that the following conditions are met:
2915
2916 * Redistributions of source code must retain the above copyright notice,
2917 this list of conditions and the following disclaimer.
2918
2919 * Redistributions in binary form must reproduce the above copyright
2920 notice, this list of conditions and the following disclaimer in the
2921 documentation and/or other materials provided with the distribution.
2922
2923 * Neither the name of the University of Cambridge nor the names of its
2924 contributors may be used to endorse or promote products derived from
2925 this software without specific prior written permission.
2926
2927THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
2928AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
2929IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
2930ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
2931LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
2932CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
2933SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
2934INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
2935CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
2936ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
2937POSSIBILITY OF SUCH DAMAGE.
2938-----------------------------------------------------------------------------
2939*/
2940
2941static const char *pcreCompileErrorCodes[] =
2942{
2943 QT_TRANSLATE_NOOP("QRegularExpression", "no error"),
2944 QT_TRANSLATE_NOOP("QRegularExpression", "\\ at end of pattern"),
2945 QT_TRANSLATE_NOOP("QRegularExpression", "\\c at end of pattern"),
2946 QT_TRANSLATE_NOOP("QRegularExpression", "unrecognized character follows \\"),
2947 QT_TRANSLATE_NOOP("QRegularExpression", "numbers out of order in {} quantifier"),
2948 QT_TRANSLATE_NOOP("QRegularExpression", "number too big in {} quantifier"),
2949 QT_TRANSLATE_NOOP("QRegularExpression", "missing terminating ] for character class"),
2950 QT_TRANSLATE_NOOP("QRegularExpression", "escape sequence is invalid in character class"),
2951 QT_TRANSLATE_NOOP("QRegularExpression", "range out of order in character class"),
2952 QT_TRANSLATE_NOOP("QRegularExpression", "quantifier does not follow a repeatable item"),
2953 QT_TRANSLATE_NOOP("QRegularExpression", "internal error: unexpected repeat"),
2954 QT_TRANSLATE_NOOP("QRegularExpression", "unrecognized character after (? or (?-"),
2955 QT_TRANSLATE_NOOP("QRegularExpression", "POSIX named classes are supported only within a class"),
2956 QT_TRANSLATE_NOOP("QRegularExpression", "POSIX collating elements are not supported"),
2957 QT_TRANSLATE_NOOP("QRegularExpression", "missing closing parenthesis"),
2958 QT_TRANSLATE_NOOP("QRegularExpression", "reference to non-existent subpattern"),
2959 QT_TRANSLATE_NOOP("QRegularExpression", "pattern passed as NULL"),
2960 QT_TRANSLATE_NOOP("QRegularExpression", "unrecognised compile-time option bit(s)"),
2961 QT_TRANSLATE_NOOP("QRegularExpression", "missing ) after (?# comment"),
2962 QT_TRANSLATE_NOOP("QRegularExpression", "parentheses are too deeply nested"),
2963 QT_TRANSLATE_NOOP("QRegularExpression", "regular expression is too large"),
2964 QT_TRANSLATE_NOOP("QRegularExpression", "failed to allocate heap memory"),
2965 QT_TRANSLATE_NOOP("QRegularExpression", "unmatched closing parenthesis"),
2966 QT_TRANSLATE_NOOP("QRegularExpression", "internal error: code overflow"),
2967 QT_TRANSLATE_NOOP("QRegularExpression", "missing closing parenthesis for condition"),
2968 QT_TRANSLATE_NOOP("QRegularExpression", "lookbehind assertion is not fixed length"),
2969 QT_TRANSLATE_NOOP("QRegularExpression", "a relative value of zero is not allowed"),
2970 QT_TRANSLATE_NOOP("QRegularExpression", "conditional subpattern contains more than two branches"),
2971 QT_TRANSLATE_NOOP("QRegularExpression", "assertion expected after (?( or (?(?C)"),
2972 QT_TRANSLATE_NOOP("QRegularExpression", "digit expected after (?+ or (?-"),
2973 QT_TRANSLATE_NOOP("QRegularExpression", "unknown POSIX class name"),
2974 QT_TRANSLATE_NOOP("QRegularExpression", "internal error in pcre2_study(): should not occur"),
2975 QT_TRANSLATE_NOOP("QRegularExpression", "this version of PCRE2 does not have Unicode support"),
2976 QT_TRANSLATE_NOOP("QRegularExpression", "parentheses are too deeply nested (stack check)"),
2977 QT_TRANSLATE_NOOP("QRegularExpression", "character code point value in \\x{} or \\o{} is too large"),
2978 QT_TRANSLATE_NOOP("QRegularExpression", "lookbehind is too complicated"),
2979 QT_TRANSLATE_NOOP("QRegularExpression", "\\C is not allowed in a lookbehind assertion in UTF-" "16" " mode"),
2980 QT_TRANSLATE_NOOP("QRegularExpression", "PCRE2 does not support \\F, \\L, \\l, \\N{name}, \\U, or \\u"),
2981 QT_TRANSLATE_NOOP("QRegularExpression", "number after (?C is greater than 255"),
2982 QT_TRANSLATE_NOOP("QRegularExpression", "closing parenthesis for (?C expected"),
2983 QT_TRANSLATE_NOOP("QRegularExpression", "invalid escape sequence in (*VERB) name"),
2984 QT_TRANSLATE_NOOP("QRegularExpression", "unrecognized character after (?P"),
2985 QT_TRANSLATE_NOOP("QRegularExpression", "syntax error in subpattern name (missing terminator?)"),
2986 QT_TRANSLATE_NOOP("QRegularExpression", "two named subpatterns have the same name (PCRE2_DUPNAMES not set)"),
2987 QT_TRANSLATE_NOOP("QRegularExpression", "subpattern name must start with a non-digit"),
2988 QT_TRANSLATE_NOOP("QRegularExpression", "this version of PCRE2 does not have support for \\P, \\p, or \\X"),
2989 QT_TRANSLATE_NOOP("QRegularExpression", "malformed \\P or \\p sequence"),
2990 QT_TRANSLATE_NOOP("QRegularExpression", "unknown property name after \\P or \\p"),
2991 QT_TRANSLATE_NOOP("QRegularExpression", "subpattern name is too long (maximum " "32" " code units)"),
2992 QT_TRANSLATE_NOOP("QRegularExpression", "too many named subpatterns (maximum " "10000" ")"),
2993 QT_TRANSLATE_NOOP("QRegularExpression", "invalid range in character class"),
2994 QT_TRANSLATE_NOOP("QRegularExpression", "octal value is greater than \\377 in 8-bit non-UTF-8 mode"),
2995 QT_TRANSLATE_NOOP("QRegularExpression", "internal error: overran compiling workspace"),
2996 QT_TRANSLATE_NOOP("QRegularExpression", "internal error: previously-checked referenced subpattern not found"),
2997 QT_TRANSLATE_NOOP("QRegularExpression", "DEFINE subpattern contains more than one branch"),
2998 QT_TRANSLATE_NOOP("QRegularExpression", "missing opening brace after \\o"),
2999 QT_TRANSLATE_NOOP("QRegularExpression", "internal error: unknown newline setting"),
3000 QT_TRANSLATE_NOOP("QRegularExpression", "\\g is not followed by a braced, angle-bracketed, or quoted name/number or by a plain number"),
3001 QT_TRANSLATE_NOOP("QRegularExpression", "(?R (recursive pattern call) must be followed by a closing parenthesis"),
3002 QT_TRANSLATE_NOOP("QRegularExpression", "obsolete error (should not occur)"),
3003 QT_TRANSLATE_NOOP("QRegularExpression", "(*VERB) not recognized or malformed"),
3004 QT_TRANSLATE_NOOP("QRegularExpression", "subpattern number is too big"),
3005 QT_TRANSLATE_NOOP("QRegularExpression", "subpattern name expected"),
3006 QT_TRANSLATE_NOOP("QRegularExpression", "internal error: parsed pattern overflow"),
3007 QT_TRANSLATE_NOOP("QRegularExpression", "non-octal character in \\o{} (closing brace missing?)"),
3008 QT_TRANSLATE_NOOP("QRegularExpression", "different names for subpatterns of the same number are not allowed"),
3009 QT_TRANSLATE_NOOP("QRegularExpression", "(*MARK) must have an argument"),
3010 QT_TRANSLATE_NOOP("QRegularExpression", "non-hex character in \\x{} (closing brace missing?)"),
3011 QT_TRANSLATE_NOOP("QRegularExpression", "\\c must be followed by a printable ASCII character"),
3012 QT_TRANSLATE_NOOP("QRegularExpression", "\\c must be followed by a letter or one of [\\‍]^_?"),
3013 QT_TRANSLATE_NOOP("QRegularExpression", "\\k is not followed by a braced, angle-bracketed, or quoted name"),
3014 QT_TRANSLATE_NOOP("QRegularExpression", "internal error: unknown meta code in check_lookbehinds()"),
3015 QT_TRANSLATE_NOOP("QRegularExpression", "\\N is not supported in a class"),
3016 QT_TRANSLATE_NOOP("QRegularExpression", "callout string is too long"),
3017 QT_TRANSLATE_NOOP("QRegularExpression", "disallowed Unicode code point (>= 0xd800 && <= 0xdfff)"),
3018 QT_TRANSLATE_NOOP("QRegularExpression", "using UTF is disabled by the application"),
3019 QT_TRANSLATE_NOOP("QRegularExpression", "using UCP is disabled by the application"),
3020 QT_TRANSLATE_NOOP("QRegularExpression", "name is too long in (*MARK), (*PRUNE), (*SKIP), or (*THEN)"),
3021 QT_TRANSLATE_NOOP("QRegularExpression", "character code point value in \\u.... sequence is too large"),
3022 QT_TRANSLATE_NOOP("QRegularExpression", "digits missing in \\x{} or \\o{} or \\N{U+}"),
3023 QT_TRANSLATE_NOOP("QRegularExpression", "syntax error or number too big in (?(VERSION condition"),
3024 QT_TRANSLATE_NOOP("QRegularExpression", "internal error: unknown opcode in auto_possessify()"),
3025 QT_TRANSLATE_NOOP("QRegularExpression", "missing terminating delimiter for callout with string argument"),
3026 QT_TRANSLATE_NOOP("QRegularExpression", "unrecognized string delimiter follows (?C"),
3027 QT_TRANSLATE_NOOP("QRegularExpression", "using \\C is disabled by the application"),
3028 QT_TRANSLATE_NOOP("QRegularExpression", "(?| and/or (?J: or (?x: parentheses are too deeply nested"),
3029 QT_TRANSLATE_NOOP("QRegularExpression", "using \\C is disabled in this PCRE2 library"),
3030 QT_TRANSLATE_NOOP("QRegularExpression", "regular expression is too complicated"),
3031 QT_TRANSLATE_NOOP("QRegularExpression", "lookbehind assertion is too long"),
3032 QT_TRANSLATE_NOOP("QRegularExpression", "pattern string is longer than the limit set by the application"),
3033 QT_TRANSLATE_NOOP("QRegularExpression", "internal error: unknown code in parsed pattern"),
3034 QT_TRANSLATE_NOOP("QRegularExpression", "internal error: bad code value in parsed_skip()"),
3035 QT_TRANSLATE_NOOP("QRegularExpression", "PCRE2_EXTRA_ALLOW_SURROGATE_ESCAPES is not allowed in UTF-16 mode"),
3036 QT_TRANSLATE_NOOP("QRegularExpression", "invalid option bits with PCRE2_LITERAL"),
3037 QT_TRANSLATE_NOOP("QRegularExpression", "\\N{U+dddd} is supported only in Unicode (UTF) mode"),
3038 QT_TRANSLATE_NOOP("QRegularExpression", "invalid hyphen in option setting"),
3039 QT_TRANSLATE_NOOP("QRegularExpression", "(*alpha_assertion) not recognized"),
3040 QT_TRANSLATE_NOOP("QRegularExpression", "script runs require Unicode support, which this version of PCRE2 does not have"),
3041 QT_TRANSLATE_NOOP("QRegularExpression", "too many capturing groups (maximum 65535)"),
3042 QT_TRANSLATE_NOOP("QRegularExpression", "atomic assertion expected after (?( or (?(?C)"),
3043 QT_TRANSLATE_NOOP("QRegularExpression", "no error"),
3044 QT_TRANSLATE_NOOP("QRegularExpression", "no match"),
3045 QT_TRANSLATE_NOOP("QRegularExpression", "partial match"),
3046 QT_TRANSLATE_NOOP("QRegularExpression", "UTF-8 error: 1 byte missing at end"),
3047 QT_TRANSLATE_NOOP("QRegularExpression", "UTF-8 error: 2 bytes missing at end"),
3048 QT_TRANSLATE_NOOP("QRegularExpression", "UTF-8 error: 3 bytes missing at end"),
3049 QT_TRANSLATE_NOOP("QRegularExpression", "UTF-8 error: 4 bytes missing at end"),
3050 QT_TRANSLATE_NOOP("QRegularExpression", "UTF-8 error: 5 bytes missing at end"),
3051 QT_TRANSLATE_NOOP("QRegularExpression", "UTF-8 error: byte 2 top bits not 0x80"),
3052 QT_TRANSLATE_NOOP("QRegularExpression", "UTF-8 error: byte 3 top bits not 0x80"),
3053 QT_TRANSLATE_NOOP("QRegularExpression", "UTF-8 error: byte 4 top bits not 0x80"),
3054 QT_TRANSLATE_NOOP("QRegularExpression", "UTF-8 error: byte 5 top bits not 0x80"),
3055 QT_TRANSLATE_NOOP("QRegularExpression", "UTF-8 error: byte 6 top bits not 0x80"),
3056 QT_TRANSLATE_NOOP("QRegularExpression", "UTF-8 error: 5-byte character is not allowed (RFC 3629)"),
3057 QT_TRANSLATE_NOOP("QRegularExpression", "UTF-8 error: 6-byte character is not allowed (RFC 3629)"),
3058 QT_TRANSLATE_NOOP("QRegularExpression", "UTF-8 error: code points greater than 0x10ffff are not defined"),
3059 QT_TRANSLATE_NOOP("QRegularExpression", "UTF-8 error: code points 0xd800-0xdfff are not defined"),
3060 QT_TRANSLATE_NOOP("QRegularExpression", "UTF-8 error: overlong 2-byte sequence"),
3061 QT_TRANSLATE_NOOP("QRegularExpression", "UTF-8 error: overlong 3-byte sequence"),
3062 QT_TRANSLATE_NOOP("QRegularExpression", "UTF-8 error: overlong 4-byte sequence"),
3063 QT_TRANSLATE_NOOP("QRegularExpression", "UTF-8 error: overlong 5-byte sequence"),
3064 QT_TRANSLATE_NOOP("QRegularExpression", "UTF-8 error: overlong 6-byte sequence"),
3065 QT_TRANSLATE_NOOP("QRegularExpression", "UTF-8 error: isolated byte with 0x80 bit set"),
3066 QT_TRANSLATE_NOOP("QRegularExpression", "UTF-8 error: illegal byte (0xfe or 0xff)"),
3067 QT_TRANSLATE_NOOP("QRegularExpression", "UTF-16 error: missing low surrogate at end"),
3068 QT_TRANSLATE_NOOP("QRegularExpression", "UTF-16 error: invalid low surrogate"),
3069 QT_TRANSLATE_NOOP("QRegularExpression", "UTF-16 error: isolated low surrogate"),
3070 QT_TRANSLATE_NOOP("QRegularExpression", "UTF-32 error: code points 0xd800-0xdfff are not defined"),
3071 QT_TRANSLATE_NOOP("QRegularExpression", "UTF-32 error: code points greater than 0x10ffff are not defined"),
3072 QT_TRANSLATE_NOOP("QRegularExpression", "bad data value"),
3073 QT_TRANSLATE_NOOP("QRegularExpression", "patterns do not all use the same character tables"),
3074 QT_TRANSLATE_NOOP("QRegularExpression", "magic number missing"),
3075 QT_TRANSLATE_NOOP("QRegularExpression", "pattern compiled in wrong mode: 8/16/32-bit error"),
3076 QT_TRANSLATE_NOOP("QRegularExpression", "bad offset value"),
3077 QT_TRANSLATE_NOOP("QRegularExpression", "bad option value"),
3078 QT_TRANSLATE_NOOP("QRegularExpression", "invalid replacement string"),
3079 QT_TRANSLATE_NOOP("QRegularExpression", "bad offset into UTF string"),
3080 QT_TRANSLATE_NOOP("QRegularExpression", "callout error code"),
3081 QT_TRANSLATE_NOOP("QRegularExpression", "invalid data in workspace for DFA restart"),
3082 QT_TRANSLATE_NOOP("QRegularExpression", "too much recursion for DFA matching"),
3083 QT_TRANSLATE_NOOP("QRegularExpression", "backreference condition or recursion test is not supported for DFA matching"),
3084 QT_TRANSLATE_NOOP("QRegularExpression", "function is not supported for DFA matching"),
3085 QT_TRANSLATE_NOOP("QRegularExpression", "pattern contains an item that is not supported for DFA matching"),
3086 QT_TRANSLATE_NOOP("QRegularExpression", "workspace size exceeded in DFA matching"),
3087 QT_TRANSLATE_NOOP("QRegularExpression", "internal error - pattern overwritten?"),
3088 QT_TRANSLATE_NOOP("QRegularExpression", "bad JIT option"),
3089 QT_TRANSLATE_NOOP("QRegularExpression", "JIT stack limit reached"),
3090 QT_TRANSLATE_NOOP("QRegularExpression", "match limit exceeded"),
3091 QT_TRANSLATE_NOOP("QRegularExpression", "no more memory"),
3092 QT_TRANSLATE_NOOP("QRegularExpression", "unknown substring"),
3093 QT_TRANSLATE_NOOP("QRegularExpression", "non-unique substring name"),
3094 QT_TRANSLATE_NOOP("QRegularExpression", "NULL argument passed"),
3095 QT_TRANSLATE_NOOP("QRegularExpression", "nested recursion at the same subject position"),
3096 QT_TRANSLATE_NOOP("QRegularExpression", "matching depth limit exceeded"),
3097 QT_TRANSLATE_NOOP("QRegularExpression", "requested value is not available"),
3098 QT_TRANSLATE_NOOP("QRegularExpression", "requested value is not set"),
3099 QT_TRANSLATE_NOOP("QRegularExpression", "offset limit set without PCRE2_USE_OFFSET_LIMIT"),
3100 QT_TRANSLATE_NOOP("QRegularExpression", "bad escape sequence in replacement string"),
3101 QT_TRANSLATE_NOOP("QRegularExpression", "expected closing curly bracket in replacement string"),
3102 QT_TRANSLATE_NOOP("QRegularExpression", "bad substitution in replacement string"),
3103 QT_TRANSLATE_NOOP("QRegularExpression", "match with end before start or start moved backwards is not supported"),
3104 QT_TRANSLATE_NOOP("QRegularExpression", "too many replacements (more than INT_MAX)"),
3105 QT_TRANSLATE_NOOP("QRegularExpression", "bad serialized data"),
3106 QT_TRANSLATE_NOOP("QRegularExpression", "heap limit exceeded"),
3107 QT_TRANSLATE_NOOP("QRegularExpression", "invalid syntax"),
3108 QT_TRANSLATE_NOOP("QRegularExpression", "internal error - duplicate substitution match"),
3109 QT_TRANSLATE_NOOP("QRegularExpression", "PCRE2_MATCH_INVALID_UTF is not supported for DFA matching"),
3110 QT_TRANSLATE_NOOP("QRegularExpression", "INTERNAL ERROR: invalid substring offset")
3111};
3112#endif // #if 0
3113
3114QT_END_NAMESPACE
QDebug operator<<(QDebug debug, const QRegularExpressionMatch &match)
Writes the match object match into the debug object debug for debugging purposes.
QDataStream & operator<<(QDataStream &out, const QRegularExpression &re)
Writes the regular expression re to stream out.
QDataStream & operator>>(QDataStream &in, QRegularExpression &re)
Reads a regular expression from stream in into re.
QDebug operator<<(QDebug debug, const QRegularExpression &re)
Writes the regular expression re into the debug object debug for debugging purposes.
QRegularExpressionMatchIteratorRangeBasedForIterator(const QRegularExpressionMatchIterator &iterator)
QDebug operator<<(QDebug debug, QDir::Filters filters)
Definition qdir.cpp:2620
static pcre2_jit_stack_16 * qtPcreCallback(void *)
static int convertToPcreOptions(QRegularExpression::PatternOptions patternOptions)
bool comparesEqual(const QRegularExpression &lhs, const QRegularExpression &rhs) noexcept
Q_DECL_COLD_FUNCTION void qtWarnAboutInvalidRegularExpression(const QString &pattern, const char *cls, const char *method)
static bool isJitEnabled()
static int safe_pcre2_match_16(const pcre2_code_16 *code, PCRE2_SPTR16 subject, qsizetype length, qsizetype startOffset, int options, pcre2_match_data_16 *matchData, pcre2_match_context_16 *matchContext)
QtPrivate::QRegularExpressionMatchIteratorRangeBasedForIterator begin(const QRegularExpressionMatchIterator &iterator)
QRegularExpressionMatchIteratorPrivate(const QRegularExpression &re, QRegularExpression::MatchType matchType, QRegularExpression::MatchOptions matchOptions, const QRegularExpressionMatch &next)
const QRegularExpression::MatchOptions matchOptions
const QRegularExpression::MatchType matchType
QRegularExpressionMatchPrivate(const QRegularExpression &re, const QString &subjectStorage, QStringView subject, QRegularExpression::MatchType matchType, QRegularExpression::MatchOptions matchOptions)
const QRegularExpression::MatchType matchType
const QRegularExpression::MatchOptions matchOptions
QRegularExpressionMatch nextMatch() const
const QRegularExpression regularExpression
QRegularExpressionPrivate(const QRegularExpressionPrivate &other)
int captureIndexForName(QAnyStringView name) const
void doMatch(QRegularExpressionMatchPrivate *priv, qsizetype offset, CheckSubjectStringOption checkSubjectStringOption=CheckSubjectString, const QRegularExpressionMatchPrivate *previous=nullptr) const
QRegularExpression::PatternOptions patternOptions