1 /*
2  * DQt - D bindings for the Qt Toolkit
3  *
4  * GNU Lesser General Public License Usage
5  * This file may be used under the terms of the GNU Lesser
6  * General Public License version 3 as published by the Free Software
7  * Foundation and appearing in the file LICENSE.LGPL3 included in the
8  * packaging of this file. Please review the following information to
9  * ensure the GNU Lesser General Public License version 3 requirements
10  * will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
11  */
12 module qt.core.regularexpression;
13 extern(C++):
14 
15 import qt.config;
16 import qt.core.flags;
17 import qt.core.global;
18 import qt.core.namespace;
19 import qt.core.shareddata;
20 import qt.core.string;
21 import qt.core.stringlist;
22 import qt.core.stringview;
23 import qt.core.typeinfo;
24 import qt.helpers;
25 
26 /+ QT_REQUIRE_CONFIG(regularexpression); +/
27 
28 
29 
30 struct QRegularExpressionPrivate;
31 
32 /+ QT_DECLARE_QESDP_SPECIALIZATION_DTOR_WITH_EXPORT(QRegularExpressionPrivate, Q_CORE_EXPORT)
33 Q_CORE_EXPORT size_t qHash(const QRegularExpression &key, size_t seed = 0) noexcept; +/
34 
35 /// Binding for C++ class [QRegularExpression](https://doc.qt.io/qt-6/qregularexpression.html).
36 @Q_RELOCATABLE_TYPE extern(C++, class) struct /+ Q_CORE_EXPORT +/ QRegularExpression
37 {
38 public:
39     enum PatternOption {
40         NoPatternOption                = 0x0000,
41         CaseInsensitiveOption          = 0x0001,
42         DotMatchesEverythingOption     = 0x0002,
43         MultilineOption                = 0x0004,
44         ExtendedPatternSyntaxOption    = 0x0008,
45         InvertedGreedinessOption       = 0x0010,
46         DontCaptureOption              = 0x0020,
47         UseUnicodePropertiesOption     = 0x0040,
48         // Formerly (no-ops deprecated in 5.12, removed 6.0):
49         // OptimizeOnFirstUsageOption = 0x0080,
50         // DontAutomaticallyOptimizeOption = 0x0100,
51     }
52     /+ Q_DECLARE_FLAGS(PatternOptions, PatternOption) +/
53 alias PatternOptions = QFlags!(PatternOption);
54     PatternOptions patternOptions() const;
55     void setPatternOptions(PatternOptions options);
56 
57     @disable this();
58     pragma(mangle, defaultConstructorMangling(__traits(identifier, typeof(this))))
59     ref typeof(this) rawConstructor();
60     static typeof(this) create()
61     {
62         typeof(this) r = typeof(this).init;
63         r.rawConstructor();
64         return r;
65     }
66 
67     /+ explicit +/this(ref const(QString) pattern, PatternOptions options = PatternOption.NoPatternOption);
68     @disable this(this);
69     this(ref const(QRegularExpression) re);
70     /+ QRegularExpression(QRegularExpression &&re) = default; +/
71     ~this();
72     /+ref QRegularExpression operator =(ref const(QRegularExpression) re);+/
73     /+ QT_MOVE_ASSIGNMENT_OPERATOR_IMPL_VIA_PURE_SWAP(QRegularExpression) +/
74 
75     /+ void swap(QRegularExpression &other) noexcept { d.swap(other.d); } +/
76 
77     QString pattern() const;
78     void setPattern(ref const(QString) pattern);
79 
80     /+ [[nodiscard]] +/
81         bool isValid() const;
82     qsizetype patternErrorOffset() const;
83     QString errorString() const;
84 
85     int captureCount() const;
86     QStringList namedCaptureGroups() const;
87 
88     enum MatchType {
89         NormalMatch = 0,
90         PartialPreferCompleteMatch,
91         PartialPreferFirstMatch,
92         NoMatch
93     }
94 
95     enum MatchOption {
96         NoMatchOption              = 0x0000,
97         AnchorAtOffsetMatchOption  = 0x0001,
98         AnchoredMatchOption /+ Q_DECL_ENUMERATOR_DEPRECATED_X(
99             "Use AnchorAtOffsetMatchOption instead") +/ = MatchOption.AnchorAtOffsetMatchOption, // Rename@Qt6.0
100         DontCheckSubjectStringMatchOption = 0x0002
101     }
102     /+ Q_DECLARE_FLAGS(MatchOptions, MatchOption) +/
103 alias MatchOptions = QFlags!(MatchOption);
104     /+ [[nodiscard]] +/
105         QRegularExpressionMatch match(ref const(QString) subject,
106                                       qsizetype offset          = 0,
107                                       MatchType matchType       = MatchType.NormalMatch,
108                                       MatchOptions matchOptions = MatchOption.NoMatchOption) const;
109 
110     /+ [[nodiscard]] +/
111         QRegularExpressionMatch match(QStringView subjectView,
112                                       qsizetype offset          = 0,
113                                       MatchType matchType       = MatchType.NormalMatch,
114                                       MatchOptions matchOptions = MatchOption.NoMatchOption) const;
115 
116     /+ [[nodiscard]] +/
117         QRegularExpressionMatchIterator globalMatch(ref const(QString) subject,
118                                                     qsizetype offset          = 0,
119                                                     MatchType matchType       = MatchType.NormalMatch,
120                                                     MatchOptions matchOptions = MatchOption.NoMatchOption) const;
121 
122     /+ [[nodiscard]] +/
123         QRegularExpressionMatchIterator globalMatch(QStringView subjectView,
124                                                     qsizetype offset          = 0,
125                                                     MatchType matchType       = MatchType.NormalMatch,
126                                                     MatchOptions matchOptions = MatchOption.NoMatchOption) const;
127 
128     void optimize() const;
129 
130     enum WildcardConversionOption {
131         DefaultWildcardConversion = 0x0,
132         UnanchoredWildcardConversion = 0x1
133     }
134     /+ Q_DECLARE_FLAGS(WildcardConversionOptions, WildcardConversionOption) +/
135 alias WildcardConversionOptions = QFlags!(WildcardConversionOption);
136     static if(QT_STRINGVIEW_LEVEL < 2)
137     {
138         static QString escape(ref const(QString) str)
139         {
140             return escape(qToStringViewIgnoringNull(str));
141         }
142 
143         static QString wildcardToRegularExpression(ref const(QString) str, WildcardConversionOptions options = WildcardConversionOption.DefaultWildcardConversion)
144         {
145             return wildcardToRegularExpression(qToStringViewIgnoringNull(str), options);
146         }
147 
148         pragma(inline, true) static QString anchoredPattern(ref const(QString) expression)
149         {
150             return anchoredPattern(qToStringViewIgnoringNull(expression));
151         }
152     }
153 
154     static QString escape(QStringView str);
155     static QString wildcardToRegularExpression(QStringView str, WildcardConversionOptions options = WildcardConversionOption.DefaultWildcardConversion);
156     static QString anchoredPattern(QStringView expression);
157 
158     static QRegularExpression fromWildcard(QStringView pattern, /+ Qt:: +/qt.core.namespace.CaseSensitivity cs = /+ Qt:: +/qt.core.namespace.CaseSensitivity.CaseInsensitive,
159                                                WildcardConversionOptions options = WildcardConversionOption.DefaultWildcardConversion);
160 
161     /+bool operator ==(ref const(QRegularExpression) re) const;+/
162     /+pragma(inline, true) bool operator !=(ref const(QRegularExpression) re) const { return !operator==(re); }+/
163 
164 private:
165     /+ friend struct QRegularExpressionPrivate; +/
166     /+ friend class QRegularExpressionMatch; +/
167     /+ friend struct QRegularExpressionMatchPrivate; +/
168     /+ friend class QRegularExpressionMatchIterator; +/
169     /+ friend Q_CORE_EXPORT size_t qHash(const QRegularExpression &key, size_t seed) noexcept; +/
170 
171     this(ref QRegularExpressionPrivate dd);
172     QExplicitlySharedDataPointer!(QRegularExpressionPrivate) d;
173     mixin(CREATE_CONVENIENCE_WRAPPERS);
174 }
175 /+pragma(inline, true) QFlags!(QRegularExpression.PatternOptions.enum_type) operator |(QRegularExpression.PatternOptions.enum_type f1, QRegularExpression.PatternOptions.enum_type f2)/+noexcept+/{return QFlags!(QRegularExpression.PatternOptions.enum_type)(f1)|f2;}+/
176 /+pragma(inline, true) QFlags!(QRegularExpression.PatternOptions.enum_type) operator |(QRegularExpression.PatternOptions.enum_type f1, QFlags!(QRegularExpression.PatternOptions.enum_type) f2)/+noexcept+/{return f2|f1;}+/
177 /+pragma(inline, true) QFlags!(QRegularExpression.PatternOptions.enum_type) operator &(QRegularExpression.PatternOptions.enum_type f1, QRegularExpression.PatternOptions.enum_type f2)/+noexcept+/{return QFlags!(QRegularExpression.PatternOptions.enum_type)(f1)&f2;}+/
178 /+pragma(inline, true) QFlags!(QRegularExpression.PatternOptions.enum_type) operator &(QRegularExpression.PatternOptions.enum_type f1, QFlags!(QRegularExpression.PatternOptions.enum_type) f2)/+noexcept+/{return f2&f1;}+/
179 /+pragma(inline, true) void operator +(QRegularExpression.PatternOptions.enum_type f1, QRegularExpression.PatternOptions.enum_type f2)/+noexcept+/;+/
180 /+pragma(inline, true) void operator +(QRegularExpression.PatternOptions.enum_type f1, QFlags!(QRegularExpression.PatternOptions.enum_type) f2)/+noexcept+/;+/
181 /+pragma(inline, true) void operator +(int f1, QFlags!(QRegularExpression.PatternOptions.enum_type) f2)/+noexcept+/;+/
182 /+pragma(inline, true) void operator -(QRegularExpression.PatternOptions.enum_type f1, QRegularExpression.PatternOptions.enum_type f2)/+noexcept+/;+/
183 /+pragma(inline, true) void operator -(QRegularExpression.PatternOptions.enum_type f1, QFlags!(QRegularExpression.PatternOptions.enum_type) f2)/+noexcept+/;+/
184 /+pragma(inline, true) void operator -(int f1, QFlags!(QRegularExpression.PatternOptions.enum_type) f2)/+noexcept+/;+/
185 /+pragma(inline, true) QIncompatibleFlag operator |(QRegularExpression.PatternOptions.enum_type f1, int f2)/+noexcept+/{return QIncompatibleFlag(int(f1)|f2);}+/
186 /+pragma(inline, true) void operator +(int f1, QRegularExpression.PatternOptions.enum_type f2)/+noexcept+/;+/
187 /+pragma(inline, true) void operator +(QRegularExpression.PatternOptions.enum_type f1, int f2)/+noexcept+/;+/
188 /+pragma(inline, true) void operator -(int f1, QRegularExpression.PatternOptions.enum_type f2)/+noexcept+/;+/
189 /+pragma(inline, true) void operator -(QRegularExpression.PatternOptions.enum_type f1, int f2)/+noexcept+/;+/
190 
191 /+ Q_DECLARE_SHARED(QRegularExpression)
192 Q_DECLARE_OPERATORS_FOR_FLAGS(QRegularExpression::PatternOptions) +/
193 /+pragma(inline, true) QFlags!(QRegularExpression.MatchOptions.enum_type) operator |(QRegularExpression.MatchOptions.enum_type f1, QRegularExpression.MatchOptions.enum_type f2)/+noexcept+/{return QFlags!(QRegularExpression.MatchOptions.enum_type)(f1)|f2;}+/
194 /+pragma(inline, true) QFlags!(QRegularExpression.MatchOptions.enum_type) operator |(QRegularExpression.MatchOptions.enum_type f1, QFlags!(QRegularExpression.MatchOptions.enum_type) f2)/+noexcept+/{return f2|f1;}+/
195 /+pragma(inline, true) QFlags!(QRegularExpression.MatchOptions.enum_type) operator &(QRegularExpression.MatchOptions.enum_type f1, QRegularExpression.MatchOptions.enum_type f2)/+noexcept+/{return QFlags!(QRegularExpression.MatchOptions.enum_type)(f1)&f2;}+/
196 /+pragma(inline, true) QFlags!(QRegularExpression.MatchOptions.enum_type) operator &(QRegularExpression.MatchOptions.enum_type f1, QFlags!(QRegularExpression.MatchOptions.enum_type) f2)/+noexcept+/{return f2&f1;}+/
197 /+pragma(inline, true) void operator +(QRegularExpression.MatchOptions.enum_type f1, QRegularExpression.MatchOptions.enum_type f2)/+noexcept+/;+/
198 /+pragma(inline, true) void operator +(QRegularExpression.MatchOptions.enum_type f1, QFlags!(QRegularExpression.MatchOptions.enum_type) f2)/+noexcept+/;+/
199 /+pragma(inline, true) void operator +(int f1, QFlags!(QRegularExpression.MatchOptions.enum_type) f2)/+noexcept+/;+/
200 /+pragma(inline, true) void operator -(QRegularExpression.MatchOptions.enum_type f1, QRegularExpression.MatchOptions.enum_type f2)/+noexcept+/;+/
201 /+pragma(inline, true) void operator -(QRegularExpression.MatchOptions.enum_type f1, QFlags!(QRegularExpression.MatchOptions.enum_type) f2)/+noexcept+/;+/
202 /+pragma(inline, true) void operator -(int f1, QFlags!(QRegularExpression.MatchOptions.enum_type) f2)/+noexcept+/;+/
203 /+pragma(inline, true) QIncompatibleFlag operator |(QRegularExpression.MatchOptions.enum_type f1, int f2)/+noexcept+/{return QIncompatibleFlag(int(f1)|f2);}+/
204 /+pragma(inline, true) void operator +(int f1, QRegularExpression.MatchOptions.enum_type f2)/+noexcept+/;+/
205 /+pragma(inline, true) void operator +(QRegularExpression.MatchOptions.enum_type f1, int f2)/+noexcept+/;+/
206 /+pragma(inline, true) void operator -(int f1, QRegularExpression.MatchOptions.enum_type f2)/+noexcept+/;+/
207 /+pragma(inline, true) void operator -(QRegularExpression.MatchOptions.enum_type f1, int f2)/+noexcept+/;+/
208 /+ Q_DECLARE_OPERATORS_FOR_FLAGS(QRegularExpression::MatchOptions)
209 #ifndef QT_NO_DATASTREAM
210 Q_CORE_EXPORT QDataStream &operator<<(QDataStream &out, const QRegularExpression &re);
211 Q_CORE_EXPORT QDataStream &operator>>(QDataStream &in, QRegularExpression &re);
212 #endif
213 
214 #ifndef QT_NO_DEBUG_STREAM
215 Q_CORE_EXPORT QDebug operator<<(QDebug debug, const QRegularExpression &re);
216 Q_CORE_EXPORT QDebug operator<<(QDebug debug, QRegularExpression::PatternOptions patternOptions);
217 #endif +/
218 
219 struct QRegularExpressionMatchPrivate;
220 /+ QT_DECLARE_QESDP_SPECIALIZATION_DTOR_WITH_EXPORT(QRegularExpressionMatchPrivate, Q_CORE_EXPORT) +/
221 /// Binding for C++ class [QRegularExpressionMatch](https://doc.qt.io/qt-6/qregularexpressionmatch.html).
222 @Q_RELOCATABLE_TYPE extern(C++, class) struct /+ Q_CORE_EXPORT +/ QRegularExpressionMatch
223 {
224 public:
225     @disable this();
226     pragma(mangle, defaultConstructorMangling(__traits(identifier, typeof(this))))
227     ref typeof(this) rawConstructor();
228     static typeof(this) create()
229     {
230         typeof(this) r = typeof(this).init;
231         r.rawConstructor();
232         return r;
233     }
234 
235     ~this();
236     @disable this(this);
237     this(ref const(QRegularExpressionMatch) match);
238     /+ QRegularExpressionMatch(QRegularExpressionMatch &&match) = default; +/
239     /+ref QRegularExpressionMatch operator =(ref const(QRegularExpressionMatch) match);+/
240     /+ QRegularExpressionMatch &operator=(QRegularExpressionMatch &&match) noexcept
241     { d.swap(match.d); return *this; } +/
242     /+ void swap(QRegularExpressionMatch &other) noexcept { d.swap(other.d); } +/
243 
244     QRegularExpression regularExpression() const;
245     QRegularExpression.MatchType matchType() const;
246     QRegularExpression.MatchOptions matchOptions() const;
247 
248     bool hasMatch() const;
249     bool hasPartialMatch() const;
250 
251     bool isValid() const;
252 
253     int lastCapturedIndex() const;
254 
255     QString captured(int nth = 0) const;
256     QStringView capturedView(int nth = 0) const;
257 
258     static if(QT_STRINGVIEW_LEVEL < 2)
259     {
260         QString captured(ref const(QString) name) const
261         { return captured(QStringView(name)); }
262     }
263 
264     QString captured(QStringView name) const;
265     QStringView capturedView(QStringView name) const;
266 
267     QStringList capturedTexts() const;
268 
269     qsizetype capturedStart(int nth = 0) const;
270     qsizetype capturedLength(int nth = 0) const;
271     qsizetype capturedEnd(int nth = 0) const;
272 
273     static if(QT_STRINGVIEW_LEVEL < 2)
274     {
275         qsizetype capturedStart(ref const(QString) name) const
276         { return capturedStart(QStringView(name)); }
277         qsizetype capturedLength(ref const(QString) name) const
278         { return capturedLength(QStringView(name)); }
279         qsizetype capturedEnd(ref const(QString) name) const
280         { return capturedEnd(QStringView(name)); }
281     }
282 
283     qsizetype capturedStart(QStringView name) const;
284     qsizetype capturedLength(QStringView name) const;
285     qsizetype capturedEnd(QStringView name) const;
286 
287 private:
288     /+ friend class QRegularExpression; +/
289     /+ friend struct QRegularExpressionMatchPrivate; +/
290     /+ friend class QRegularExpressionMatchIterator; +/
291 
292     this(ref QRegularExpressionMatchPrivate dd);
293     QExplicitlySharedDataPointer!(QRegularExpressionMatchPrivate) d;
294     mixin(CREATE_CONVENIENCE_WRAPPERS);
295 }
296 
297 /+ Q_DECLARE_SHARED(QRegularExpressionMatch)
298 
299 #ifndef QT_NO_DEBUG_STREAM
300 Q_CORE_EXPORT QDebug operator<<(QDebug debug, const QRegularExpressionMatch &match);
301 #endif +/
302 
303 extern(C++, "QtPrivate") {
304 extern(C++, class) struct QRegularExpressionMatchIteratorRangeBasedForIteratorSentinel {}
305 }
306 
307 struct QRegularExpressionMatchIteratorPrivate;
308 /+ QT_DECLARE_QESDP_SPECIALIZATION_DTOR_WITH_EXPORT(QRegularExpressionMatchIteratorPrivate, Q_CORE_EXPORT) +/
309 /// Binding for C++ class [QRegularExpressionMatchIterator](https://doc.qt.io/qt-6/qregularexpressionmatchiterator.html).
310 @Q_RELOCATABLE_TYPE extern(C++, class) struct /+ Q_CORE_EXPORT +/ QRegularExpressionMatchIterator
311 {
312 public:
313     @disable this();
314     pragma(mangle, defaultConstructorMangling(__traits(identifier, typeof(this))))
315     ref typeof(this) rawConstructor();
316     static typeof(this) create()
317     {
318         typeof(this) r = typeof(this).init;
319         r.rawConstructor();
320         return r;
321     }
322 
323     ~this();
324     @disable this(this);
325     this(ref const(QRegularExpressionMatchIterator) iterator);
326     /+ QRegularExpressionMatchIterator(QRegularExpressionMatchIterator &&iterator) = default; +/
327     /+ref QRegularExpressionMatchIterator operator =(ref const(QRegularExpressionMatchIterator) iterator);+/
328     /+ QRegularExpressionMatchIterator &operator=(QRegularExpressionMatchIterator &&iterator) noexcept
329     { d.swap(iterator.d); return *this; } +/
330     /+ void swap(QRegularExpressionMatchIterator &other) noexcept { d.swap(other.d); } +/
331 
332     bool isValid() const;
333 
334     bool hasNext() const;
335     QRegularExpressionMatch next();
336     QRegularExpressionMatch peekNext() const;
337 
338     QRegularExpression regularExpression() const;
339     QRegularExpression.MatchType matchType() const;
340     QRegularExpression.MatchOptions matchOptions() const;
341 
342 private:
343     /+ friend class QRegularExpression; +/
344     /+ friend Q_CORE_EXPORT QtPrivate::QRegularExpressionMatchIteratorRangeBasedForIterator begin(const QRegularExpressionMatchIterator &iterator); +/
345     /+ friend QtPrivate::QRegularExpressionMatchIteratorRangeBasedForIteratorSentinel end(const QRegularExpressionMatchIterator &) { return {}; } +/
346 
347     this(ref QRegularExpressionMatchIteratorPrivate dd);
348     QExplicitlySharedDataPointer!(QRegularExpressionMatchIteratorPrivate) d;
349     mixin(CREATE_CONVENIENCE_WRAPPERS);
350 }
351 
352 extern(C++, "QtPrivate") {
353 
354 // support for range-based for loop
355 extern(C++, class) struct QRegularExpressionMatchIteratorRangeBasedForIterator
356 {
357 public:
358     alias value_type = QRegularExpressionMatch;
359     alias difference_type = int;
360 //    alias reference_type = ref const(QRegularExpressionMatch);
361     alias pointer_type = const(QRegularExpressionMatch)*;
362 //    alias iterator_category = /+ std:: +/forward_iterator_tag;
363 
364     @disable this();
365     /+this()
366     {
367         this.m_atEnd = true;
368     }+/
369 
370     /+/+ explicit +/this(ref const(QRegularExpressionMatchIterator) iterator)
371     {
372         this.m_matchIterator = iterator;
373         this.m_currentMatch = typeof(this.m_currentMatch)();
374         this.m_atEnd = false;
375 
376         ++this;
377     }+/
378 
379     ref const(QRegularExpressionMatch) opUnary(string op)() const if(op == "*")
380     {
381         (mixin(Q_ASSERT_X(q{!m_atEnd},q{ Q_FUNC_INFO},q{ "operator* called on an iterator already at the end"})));
382         return m_currentMatch;
383     }
384 
385     ref QRegularExpressionMatchIteratorRangeBasedForIterator opUnary(string op)() if(op == "++")
386     {
387         (mixin(Q_ASSERT_X(q{!m_atEnd},q{ Q_FUNC_INFO},q{ "operator++ called on an iterator already at the end"})));
388         if (m_matchIterator.hasNext()) {
389             m_currentMatch = m_matchIterator.next();
390         } else {
391             m_currentMatch = QRegularExpressionMatch();
392             m_atEnd = true;
393         }
394 
395         return this;
396     }
397 
398     /+QRegularExpressionMatchIteratorRangeBasedForIterator operator ++(int)
399     {
400         QRegularExpressionMatchIteratorRangeBasedForIterator i = this;
401         ++this;
402         return i;
403     }+/
404 
405 private:
406     // [input.iterators] imposes operator== on us. Unfortunately, it's not
407     // trivial to implement, so just do the bare minimum to satifisfy
408     // Cpp17EqualityComparable.
409     /+ friend bool operator==(const QRegularExpressionMatchIteratorRangeBasedForIterator &lhs,
410                            const QRegularExpressionMatchIteratorRangeBasedForIterator &rhs) noexcept
411     {
412         return (&lhs == &rhs);
413     } +/
414 
415     /+ friend bool operator!=(const QRegularExpressionMatchIteratorRangeBasedForIterator &lhs,
416                            const QRegularExpressionMatchIteratorRangeBasedForIterator &rhs) noexcept
417     {
418         return !(lhs == rhs);
419     } +/
420 
421     // This is what we really use in a range-based for.
422     /+ friend bool operator==(const QRegularExpressionMatchIteratorRangeBasedForIterator &lhs,
423                            QRegularExpressionMatchIteratorRangeBasedForIteratorSentinel) noexcept
424     {
425         return lhs.m_atEnd;
426     } +/
427 
428     /+ friend bool operator!=(const QRegularExpressionMatchIteratorRangeBasedForIterator &lhs,
429                            QRegularExpressionMatchIteratorRangeBasedForIteratorSentinel) noexcept
430     {
431         return !lhs.m_atEnd;
432     } +/
433 
434     QRegularExpressionMatchIterator m_matchIterator;
435     QRegularExpressionMatch m_currentMatch;
436     bool m_atEnd;
437 }
438 
439 } // namespace QtPrivate
440 
441 /+ Q_DECLARE_SHARED(QRegularExpressionMatchIterator) +/
442