1/****************************************************************************
2**
3** Copyright (C) 2016 The Qt Company Ltd.
4** Contact: https://www.qt.io/licensing/
5**
6** This file is part of the Qt Linguist of the Qt Toolkit.
7**
8** $QT_BEGIN_LICENSE:GPL-EXCEPT$
9** Commercial License Usage
10** Licensees holding valid commercial Qt licenses may use this file in
11** accordance with the commercial license agreement provided with the
12** Software or, alternatively, in accordance with the terms contained in
13** a written agreement between you and The Qt Company. For licensing terms
14** and conditions see https://www.qt.io/terms-conditions. For further
15** information use the contact form at https://www.qt.io/contact-us.
16**
17** GNU General Public License Usage
18** Alternatively, this file may be used under the terms of the GNU
19** General Public License version 3 as published by the Free Software
20** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
21** included in the packaging of this file. Please review the following
22** information to ensure the GNU General Public License requirements will
23** be met: https://www.gnu.org/licenses/gpl-3.0.html.
24**
25** $QT_END_LICENSE$
26**
27****************************************************************************/
28
29#ifndef PROITEMS_H
30#define PROITEMS_H
31
32#include "qmake_global.h"
33
34#include <qstring.h>
35#include <qvector.h>
36#include <qhash.h>
37
38QT_BEGIN_NAMESPACE
39
40class QTextStream;
41
42#ifdef PROPARSER_THREAD_SAFE
43typedef QAtomicInt ProItemRefCount;
44#else
45class ProItemRefCount {
46public:
47 ProItemRefCount(int cnt = 0) : m_cnt(cnt) {}
48 bool ref() { return ++m_cnt != 0; }
49 bool deref() { return --m_cnt != 0; }
50 ProItemRefCount &operator=(int value) { m_cnt = value; return *this; }
51private:
52 int m_cnt;
53};
54#endif
55
56#ifndef QT_BUILD_QMAKE
57# define PROITEM_EXPLICIT explicit
58#else
59# define PROITEM_EXPLICIT
60#endif
61
62class ProKey;
63class ProStringList;
64class ProFile;
65
66class ProString {
67public:
68 ProString();
69 ProString(const ProString &other);
70 ProString &operator=(const ProString &) = default;
71 PROITEM_EXPLICIT ProString(const QString &str);
72 PROITEM_EXPLICIT ProString(const QStringRef &str);
73 PROITEM_EXPLICIT ProString(const char *str);
74 ProString(const QString &str, int offset, int length);
75 void setValue(const QString &str);
76 void clear() { m_string.clear(); m_length = 0; }
77 ProString &setSource(const ProString &other) { m_file = other.m_file; return *this; }
78 ProString &setSource(int id) { m_file = id; return *this; }
79 int sourceFile() const { return m_file; }
80
81 ProString &prepend(const ProString &other);
82 ProString &append(const ProString &other, bool *pending = nullptr);
83 ProString &append(const QString &other) { return append(other: ProString(other)); }
84 ProString &append(const QLatin1String other);
85 ProString &append(const char *other) { return append(other: QLatin1String(other)); }
86 ProString &append(QChar other);
87 ProString &append(const ProStringList &other, bool *pending = nullptr, bool skipEmpty1st = false);
88 ProString &operator+=(const ProString &other) { return append(other); }
89 ProString &operator+=(const QString &other) { return append(other); }
90 ProString &operator+=(const QLatin1String other) { return append(other); }
91 ProString &operator+=(const char *other) { return append(other); }
92 ProString &operator+=(QChar other) { return append(other); }
93
94 void chop(int n) { Q_ASSERT(n <= m_length); m_length -= n; }
95 void chopFront(int n) { Q_ASSERT(n <= m_length); m_offset += n; m_length -= n; }
96
97 bool operator==(const ProString &other) const { return toQStringRef() == other.toQStringRef(); }
98 bool operator==(const QString &other) const { return toQStringRef() == other; }
99 bool operator==(const QStringRef &other) const { return toQStringRef() == other; }
100 bool operator==(QLatin1String other) const { return toQStringRef() == other; }
101 bool operator==(const char *other) const { return toQStringRef() == QLatin1String(other); }
102 bool operator!=(const ProString &other) const { return !(*this == other); }
103 bool operator!=(const QString &other) const { return !(*this == other); }
104 bool operator!=(QLatin1String other) const { return !(*this == other); }
105 bool operator!=(const char *other) const { return !(*this == other); }
106 bool operator<(const ProString &other) const { return toQStringRef() < other.toQStringRef(); }
107 bool isNull() const { return m_string.isNull(); }
108 bool isEmpty() const { return !m_length; }
109 int length() const { return m_length; }
110 int size() const { return m_length; }
111 QChar at(int i) const { Q_ASSERT((uint)i < (uint)m_length); return constData()[i]; }
112 const QChar *constData() const { return m_string.constData() + m_offset; }
113 ProString mid(int off, int len = -1) const;
114 ProString left(int len) const { return mid(off: 0, len); }
115 ProString right(int len) const { return mid(off: qMax(a: 0, b: size() - len)); }
116 ProString trimmed() const;
117 int compare(const ProString &sub, Qt::CaseSensitivity cs = Qt::CaseSensitive) const { return toQStringRef().compare(s: sub.toQStringRef(), cs); }
118 int compare(const QString &sub, Qt::CaseSensitivity cs = Qt::CaseSensitive) const { return toQStringRef().compare(s: sub, cs); }
119 int compare(const char *sub, Qt::CaseSensitivity cs = Qt::CaseSensitive) const { return toQStringRef().compare(s: QLatin1String(sub), cs); }
120 bool startsWith(const ProString &sub, Qt::CaseSensitivity cs = Qt::CaseSensitive) const { return toQStringRef().startsWith(c: sub.toQStringRef(), cs); }
121 bool startsWith(const QString &sub, Qt::CaseSensitivity cs = Qt::CaseSensitive) const { return toQStringRef().startsWith(s: sub, cs); }
122 bool startsWith(const char *sub, Qt::CaseSensitivity cs = Qt::CaseSensitive) const { return toQStringRef().startsWith(s: QLatin1String(sub), cs); }
123 bool startsWith(QChar c, Qt::CaseSensitivity cs = Qt::CaseSensitive) const { return toQStringRef().startsWith(c, cs); }
124 bool endsWith(const ProString &sub, Qt::CaseSensitivity cs = Qt::CaseSensitive) const { return toQStringRef().endsWith(c: sub.toQStringRef(), cs); }
125 bool endsWith(const QString &sub, Qt::CaseSensitivity cs = Qt::CaseSensitive) const { return toQStringRef().endsWith(s: sub, cs); }
126 bool endsWith(const char *sub, Qt::CaseSensitivity cs = Qt::CaseSensitive) const { return toQStringRef().endsWith(s: QLatin1String(sub), cs); }
127 bool endsWith(QChar c, Qt::CaseSensitivity cs = Qt::CaseSensitive) const { return toQStringRef().endsWith(c, cs); }
128 int indexOf(const QString &s, int from = 0, Qt::CaseSensitivity cs = Qt::CaseSensitive) const { return toQStringRef().indexOf(str: s, from, cs); }
129 int indexOf(const char *s, int from = 0, Qt::CaseSensitivity cs = Qt::CaseSensitive) const { return toQStringRef().indexOf(str: QLatin1String(s), from, cs); }
130 int indexOf(QChar c, int from = 0, Qt::CaseSensitivity cs = Qt::CaseSensitive) const { return toQStringRef().indexOf(ch: c, from, cs); }
131 int lastIndexOf(const QString &s, int from = -1, Qt::CaseSensitivity cs = Qt::CaseSensitive) const { return toQStringRef().lastIndexOf(str: s, from, cs); }
132 int lastIndexOf(const char *s, int from = -1, Qt::CaseSensitivity cs = Qt::CaseSensitive) const { return toQStringRef().lastIndexOf(str: QLatin1String(s), from, cs); }
133 int lastIndexOf(QChar c, int from = -1, Qt::CaseSensitivity cs = Qt::CaseSensitive) const { return toQStringRef().lastIndexOf(ch: c, from, cs); }
134 bool contains(const QString &s, Qt::CaseSensitivity cs = Qt::CaseSensitive) const { return indexOf(s, from: 0, cs) >= 0; }
135 bool contains(const char *s, Qt::CaseSensitivity cs = Qt::CaseSensitive) const { return indexOf(s: QLatin1String(s), from: 0, cs) >= 0; }
136 bool contains(QChar c, Qt::CaseSensitivity cs = Qt::CaseSensitive) const { return indexOf(c, from: 0, cs) >= 0; }
137 int toLongLong(bool *ok = nullptr, int base = 10) const { return toQStringRef().toLongLong(ok, base); }
138 int toInt(bool *ok = nullptr, int base = 10) const { return toQStringRef().toInt(ok, base); }
139 short toShort(bool *ok = nullptr, int base = 10) const { return toQStringRef().toShort(ok, base); }
140
141 uint hash() const { return m_hash; }
142 static uint hash(const QChar *p, int n);
143
144 ALWAYS_INLINE QStringRef toQStringRef() const { return QStringRef(&m_string, m_offset, m_length); }
145 ALWAYS_INLINE QStringView toQStringView() const { return QStringView(m_string).mid(pos: m_offset, n: m_length); }
146
147 ALWAYS_INLINE ProKey &toKey() { return *(ProKey *)this; }
148 ALWAYS_INLINE const ProKey &toKey() const { return *(const ProKey *)this; }
149
150 QString toQString() const;
151 QString &toQString(QString &tmp) const;
152
153 QByteArray toLatin1() const { return toQStringRef().toLatin1(); }
154
155private:
156 ProString(const ProKey &other);
157 ProString &operator=(const ProKey &other);
158
159 enum OmitPreHashing { NoHash };
160 ProString(const ProString &other, OmitPreHashing);
161
162 enum DoPreHashing { DoHash };
163 ALWAYS_INLINE ProString(const QString &str, DoPreHashing);
164 ALWAYS_INLINE ProString(const char *str, DoPreHashing);
165 ALWAYS_INLINE ProString(const QString &str, int offset, int length, DoPreHashing);
166 ALWAYS_INLINE ProString(const QString &str, int offset, int length, uint hash);
167
168 QString m_string;
169 int m_offset, m_length;
170 int m_file;
171 mutable uint m_hash;
172 QChar *prepareExtend(int extraLen, int thisTarget, int extraTarget);
173 uint updatedHash() const;
174 friend uint qHash(const ProString &str);
175 friend QString operator+(const ProString &one, const ProString &two);
176 friend class ProKey;
177};
178Q_DECLARE_TYPEINFO(ProString, Q_MOVABLE_TYPE);
179
180class ProKey : public ProString {
181public:
182 ALWAYS_INLINE ProKey() : ProString() {}
183 explicit ProKey(const QString &str);
184 PROITEM_EXPLICIT ProKey(const char *str);
185 ProKey(const QString &str, int off, int len);
186 ProKey(const QString &str, int off, int len, uint hash);
187 void setValue(const QString &str);
188
189#ifdef Q_CC_MSVC
190 // Workaround strange MSVC behaviour when exporting classes with ProKey members.
191 ALWAYS_INLINE ProKey(const ProKey &other) : ProString(other.toString()) {}
192 ALWAYS_INLINE ProKey &operator=(const ProKey &other)
193 {
194 toString() = other.toString();
195 return *this;
196 }
197#endif
198
199 ALWAYS_INLINE ProString &toString() { return *(ProString *)this; }
200 ALWAYS_INLINE const ProString &toString() const { return *(const ProString *)this; }
201
202private:
203 ProKey(const ProString &other);
204};
205Q_DECLARE_TYPEINFO(ProKey, Q_MOVABLE_TYPE);
206
207uint qHash(const ProString &str);
208QString operator+(const ProString &one, const ProString &two);
209inline QString operator+(const ProString &one, const QString &two)
210 { return one.toQStringRef() + two; }
211inline QString operator+(const QString &one, const ProString &two)
212 { return one + two.toQStringRef(); }
213
214inline QString operator+(const ProString &one, const char *two)
215 { return one.toQStringRef() + QLatin1String(two); }
216inline QString operator+(const char *one, const ProString &two)
217 { return QLatin1String(one) + two.toQStringRef(); }
218inline QString operator+(const ProString &one, QChar two)
219 { return one.toQStringRef() + two; }
220inline QString operator+(QChar one, const ProString &two)
221 { return one + two.toQStringRef(); }
222
223inline QString &operator+=(QString &that, const ProString &other)
224 { return that += other.toQStringRef(); }
225
226inline bool operator==(const QString &that, const ProString &other)
227 { return other == that; }
228inline bool operator!=(const QString &that, const ProString &other)
229 { return !(other == that); }
230
231QTextStream &operator<<(QTextStream &t, const ProString &str);
232
233// This class manages read-only access to a ProString via a raw data QString
234// temporary, ensuring that the latter is accessed exclusively.
235class ProStringRoUser
236{
237public:
238 ProStringRoUser(QString &rs)
239 {
240 Q_ASSERT(rs.isDetached() || rs.isEmpty());
241 m_rs = &rs;
242 }
243 ProStringRoUser(const ProString &ps, QString &rs)
244 : ProStringRoUser(rs)
245 {
246 ps.toQString(tmp&: rs);
247 }
248 // No destructor, as a RAII pattern cannot be used: references to the
249 // temporary string can legitimately outlive instances of this class
250 // (if they are held by Qt, e.g. in QRegExp).
251 QString &set(const ProString &ps) { return ps.toQString(tmp&: *m_rs); }
252 QString &str() { return *m_rs; }
253
254protected:
255 QString *m_rs;
256};
257
258// This class manages read-write access to a ProString via a raw data QString
259// temporary, ensuring that the latter is accessed exclusively, and that raw
260// data does not leak outside its source's refcounting.
261class ProStringRwUser : public ProStringRoUser
262{
263public:
264 ProStringRwUser(QString &rs)
265 : ProStringRoUser(rs), m_ps(nullptr) {}
266 ProStringRwUser(const ProString &ps, QString &rs)
267 : ProStringRoUser(ps, rs), m_ps(&ps) {}
268 QString &set(const ProString &ps) { m_ps = &ps; return ProStringRoUser::set(ps); }
269 ProString extract(const QString &s) const
270 { return s.isSharedWith(other: *m_rs) ? *m_ps : ProString(s).setSource(*m_ps); }
271 ProString extract(const QString &s, const ProStringRwUser &other) const
272 {
273 if (other.m_ps && s.isSharedWith(other: *other.m_rs))
274 return *other.m_ps;
275 return extract(s);
276 }
277
278private:
279 const ProString *m_ps;
280};
281
282class ProStringList : public QVector<ProString> {
283public:
284 ProStringList() {}
285 ProStringList(const ProString &str) { *this << str; }
286 explicit ProStringList(const QStringList &list);
287 QStringList toQStringList() const;
288
289 ProStringList &operator<<(const ProString &str)
290 { QVector<ProString>::operator<<(t: str); return *this; }
291
292 int length() const { return size(); }
293
294 QString join(const ProString &sep) const;
295 QString join(const QString &sep) const;
296 QString join(QChar sep) const;
297
298 void insertUnique(const ProStringList &value);
299
300 void removeAll(const ProString &str);
301 void removeAll(const char *str);
302 void removeEach(const ProStringList &value);
303 void removeAt(int idx) { remove(i: idx); }
304 void removeEmpty();
305 void removeDuplicates();
306
307 bool contains(const ProString &str, Qt::CaseSensitivity cs = Qt::CaseSensitive) const;
308 bool contains(const QStringRef &str, Qt::CaseSensitivity cs = Qt::CaseSensitive) const;
309 bool contains(const QString &str, Qt::CaseSensitivity cs = Qt::CaseSensitive) const
310 { return contains(str: ProString(str), cs); }
311 bool contains(const char *str, Qt::CaseSensitivity cs = Qt::CaseSensitive) const;
312};
313Q_DECLARE_TYPEINFO(ProStringList, Q_MOVABLE_TYPE);
314
315inline ProStringList operator+(const ProStringList &one, const ProStringList &two)
316 { ProStringList ret = one; ret += two; return ret; }
317
318typedef QHash<ProKey, ProStringList> ProValueMap;
319
320// These token definitions affect both ProFileEvaluator and ProWriter
321enum ProToken {
322 TokTerminator = 0, // end of stream (possibly not included in length; must be zero)
323 TokLine, // line marker:
324 // - line (1)
325 TokAssign, // variable =
326 TokAppend, // variable +=
327 TokAppendUnique, // variable *=
328 TokRemove, // variable -=
329 TokReplace, // variable ~=
330 // previous literal/expansion is a variable manipulation
331 // - lower bound for expected output length (1)
332 // - value expression + TokValueTerminator
333 TokValueTerminator, // assignment value terminator
334 TokLiteral, // literal string (fully dequoted)
335 // - length (1)
336 // - string data (length; unterminated)
337 TokHashLiteral, // literal string with hash (fully dequoted)
338 // - hash (2)
339 // - length (1)
340 // - string data (length; unterminated)
341 TokVariable, // qmake variable expansion
342 // - hash (2)
343 // - name length (1)
344 // - name (name length; unterminated)
345 TokProperty, // qmake property expansion
346 // - hash (2)
347 // - name length (1)
348 // - name (name length; unterminated)
349 TokEnvVar, // environment variable expansion
350 // - name length (1)
351 // - name (name length; unterminated)
352 TokFuncName, // replace function expansion
353 // - hash (2)
354 // - name length (1)
355 // - name (name length; unterminated)
356 // - ((nested expansion + TokArgSeparator)* + nested expansion)?
357 // - TokFuncTerminator
358 TokArgSeparator, // function argument separator
359 TokFuncTerminator, // function argument list terminator
360 TokCondition, // previous literal/expansion is a conditional
361 TokTestCall, // previous literal/expansion is a test function call
362 // - ((nested expansion + TokArgSeparator)* + nested expansion)?
363 // - TokFuncTerminator
364 TokReturn, // previous literal/expansion is a return value
365 TokBreak, // break loop
366 TokNext, // shortcut to next loop iteration
367 TokNot, // '!' operator
368 TokAnd, // ':' operator
369 TokOr, // '|' operator
370 TokBranch, // branch point:
371 // - then block length (2)
372 // - then block + TokTerminator (then block length)
373 // - else block length (2)
374 // - else block + TokTerminator (else block length)
375 TokForLoop, // for loop:
376 // - variable name: hash (2), length (1), chars (length)
377 // - expression: length (2), bytes + TokValueTerminator (length)
378 // - body length (2)
379 // - body + TokTerminator (body length)
380 TokTestDef, // test function definition:
381 TokReplaceDef, // replace function definition:
382 // - function name: hash (2), length (1), chars (length)
383 // - body length (2)
384 // - body + TokTerminator (body length)
385 TokBypassNesting, // escape from function local variable scopes:
386 // - block length (2)
387 // - block + TokTerminator (block length)
388 TokMask = 0xff,
389 TokQuoted = 0x100, // The expression is quoted => join expanded stringlist
390 TokNewStr = 0x200 // Next stringlist element
391};
392
393class QMAKE_EXPORT ProFile
394{
395public:
396 ProFile(int id, const QString &fileName);
397 ~ProFile();
398
399 int id() const { return m_id; }
400 QString fileName() const { return m_fileName; }
401 QString directoryName() const { return m_directoryName; }
402 const QString &items() const { return m_proitems; }
403 QString *itemsRef() { return &m_proitems; }
404 const ushort *tokPtr() const { return (const ushort *)m_proitems.constData(); }
405 const ushort *tokPtrEnd() const { return (const ushort *)m_proitems.constData() + m_proitems.size(); }
406
407 void ref() { m_refCount.ref(); }
408 void deref() { if (!m_refCount.deref()) delete this; }
409
410 bool isOk() const { return m_ok; }
411 void setOk(bool ok) { m_ok = ok; }
412
413 bool isHostBuild() const { return m_hostBuild; }
414 void setHostBuild(bool host_build) { m_hostBuild = host_build; }
415
416 ProString getStr(const ushort *&tPtr);
417 ProKey getHashStr(const ushort *&tPtr);
418
419private:
420 ProItemRefCount m_refCount;
421 QString m_proitems;
422 QString m_fileName;
423 QString m_directoryName;
424 int m_id;
425 bool m_ok;
426 bool m_hostBuild;
427};
428
429class ProFunctionDef {
430public:
431 ProFunctionDef(ProFile *pro, int offset) : m_pro(pro), m_offset(offset) { m_pro->ref(); }
432 ProFunctionDef(const ProFunctionDef &o) : m_pro(o.m_pro), m_offset(o.m_offset) { m_pro->ref(); }
433 ProFunctionDef(ProFunctionDef &&other) Q_DECL_NOTHROW
434 : m_pro(other.m_pro), m_offset(other.m_offset) { other.m_pro = nullptr; }
435 ~ProFunctionDef() { if (m_pro) m_pro->deref(); }
436 ProFunctionDef &operator=(const ProFunctionDef &o)
437 {
438 if (this != &o) {
439 if (m_pro)
440 m_pro->deref();
441 m_pro = o.m_pro;
442 m_pro->ref();
443 m_offset = o.m_offset;
444 }
445 return *this;
446 }
447 ProFunctionDef &operator=(ProFunctionDef &&other) Q_DECL_NOTHROW
448 {
449 ProFunctionDef moved(std::move(other));
450 swap(other&: moved);
451 return *this;
452 }
453 void swap(ProFunctionDef &other) Q_DECL_NOTHROW
454 {
455 qSwap(value1&: m_pro, value2&: other.m_pro);
456 qSwap(value1&: m_offset, value2&: other.m_offset);
457 }
458
459 ProFile *pro() const { return m_pro; }
460 const ushort *tokPtr() const { return m_pro->tokPtr() + m_offset; }
461private:
462 ProFile *m_pro;
463 int m_offset;
464};
465
466Q_DECLARE_TYPEINFO(ProFunctionDef, Q_MOVABLE_TYPE);
467
468struct ProFunctionDefs {
469 QHash<ProKey, ProFunctionDef> testFunctions;
470 QHash<ProKey, ProFunctionDef> replaceFunctions;
471};
472
473QT_END_NAMESPACE
474
475#endif // PROITEMS_H
476

source code of qttools/src/linguist/shared/proitems.h