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