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

Provided by KDAB

Privacy Policy
Start learning QML with our Intro Training
Find out more

source code of qtbase/src/corelib/text/qregularexpression.cpp