1// Copyright (C) 2016 The Qt Company Ltd.
2// Copyright (C) 2013 Olivier Goffart <ogoffart@woboq.com>
3// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
4
5#ifndef SYMBOLS_H
6#define SYMBOLS_H
7
8#include "token.h"
9#include <qhashfunctions.h>
10#include <qlist.h>
11#include <qstack.h>
12#include <qstring.h>
13#include <qset.h>
14
15QT_BEGIN_NAMESPACE
16
17struct SubArray
18{
19 inline SubArray() = default;
20 inline SubArray(const QByteArray &a):array(a),from(0), len(a.size()){}
21 inline SubArray(const char *s):array(s),from(0) { len = array.size(); }
22 SubArray(const QByteArray &a, qsizetype from, qsizetype len)
23 : array(a), from(from), len(len)
24 {
25 }
26 QByteArray array;
27 qsizetype from = 0;
28 qsizetype len = -1;
29 inline bool operator==(const SubArray &other) const {
30 if (len != other.len)
31 return false;
32 const auto begin = array.cbegin() + from;
33 const auto end = begin + len;
34 const auto other_begin = other.array.cbegin() + other.from;
35 return std::equal(first1: begin, last1: end, first2: other_begin);
36 }
37};
38
39inline size_t qHash(const SubArray &key, size_t seed = 0)
40{
41 return qHash(key: QLatin1StringView(key.array.constData() + key.from, key.len), seed);
42}
43
44
45struct Symbol
46{
47 inline Symbol() = default;
48 inline Symbol(int lineNum, Token token) : lineNum(lineNum), token(token) { }
49 inline Symbol(int lineNum, Token token, const QByteArray &lexem)
50 : lineNum(lineNum), token(token), lex(lexem), len(lex.size())
51 {
52 }
53 Symbol(int lineNum, Token token, const QByteArray &lexem, qsizetype from, qsizetype len)
54 : lineNum(lineNum), token(token), lex(lexem), from(from), len(len)
55 {
56 }
57 int lineNum = -1;
58 Token token = NOTOKEN;
59 inline QByteArray lexem() const { return lex.mid(index: from, len); }
60 inline QByteArray unquotedLexem() const { return lex.mid(index: from+1, len: len-2); }
61 inline QByteArrayView lexemView() const { return QByteArrayView{lex}.mid(pos: from, n: len); }
62 inline QByteArrayView unquotedLexemView() const { return QByteArrayView{lex}.mid(pos: from+1, n: len-2); }
63 void mergeStringLiteral(const Symbol &next);
64 inline operator SubArray() const { return SubArray(lex, from, len); }
65 bool operator==(const Symbol& o) const
66 {
67 return SubArray(lex, from, len) == SubArray(o.lex, o.from, o.len);
68 }
69 QByteArray lex;
70 qsizetype from = 0;
71 qsizetype len = -1;
72};
73Q_DECLARE_TYPEINFO(Symbol, Q_RELOCATABLE_TYPE);
74
75typedef QList<Symbol> Symbols;
76
77struct SafeSymbols {
78 Symbols symbols;
79 QByteArray expandedMacro;
80 QSet<QByteArray> excludedSymbols;
81 qsizetype index;
82};
83Q_DECLARE_TYPEINFO(SafeSymbols, Q_RELOCATABLE_TYPE);
84
85class SymbolStack : public QStack<SafeSymbols>
86{
87public:
88 inline bool hasNext() {
89 while (!isEmpty() && top().index >= top().symbols.size())
90 pop();
91 return !isEmpty();
92 }
93 inline Token next() {
94 while (!isEmpty() && top().index >= top().symbols.size())
95 pop();
96 if (isEmpty())
97 return NOTOKEN;
98 return top().symbols.at(i: top().index++).token;
99 }
100 bool test(Token);
101 inline const Symbol &symbol() const { return top().symbols.at(i: top().index-1); }
102 inline Token token() { return symbol().token; }
103 inline QByteArray lexem() const { return symbol().lexem(); }
104 inline QByteArray unquotedLexem() { return symbol().unquotedLexem(); }
105
106 bool dontReplaceSymbol(const QByteArray &name) const;
107 QSet<QByteArray> excludeSymbols() const;
108};
109
110inline bool SymbolStack::test(Token token)
111{
112 qsizetype stackPos = size() - 1;
113 while (stackPos >= 0 && at(i: stackPos).index >= at(i: stackPos).symbols.size())
114 --stackPos;
115 if (stackPos < 0)
116 return false;
117 if (at(i: stackPos).symbols.at(i: at(i: stackPos).index).token == token) {
118 next();
119 return true;
120 }
121 return false;
122}
123
124inline bool SymbolStack::dontReplaceSymbol(const QByteArray &name) const
125{
126 auto matchesName = [&name](const SafeSymbols &sf) {
127 return name == sf.expandedMacro || sf.excludedSymbols.contains(value: name);
128 };
129 return std::any_of(first: cbegin(), last: cend(), pred: matchesName);
130}
131
132inline QSet<QByteArray> SymbolStack::excludeSymbols() const
133{
134 QSet<QByteArray> set;
135 for (const SafeSymbols &sf : *this) {
136 set << sf.expandedMacro;
137 set += sf.excludedSymbols;
138 }
139 return set;
140}
141
142QT_END_NAMESPACE
143
144#endif // SYMBOLS_H
145

source code of qtbase/src/tools/moc/symbols.h