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 QtCore module of the Qt Toolkit.
7**
8** $QT_BEGIN_LICENSE:LGPL$
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 Lesser General Public License Usage
18** Alternatively, this file may be used under the terms of the GNU Lesser
19** General Public License version 3 as published by the Free Software
20** Foundation and appearing in the file LICENSE.LGPL3 included in the
21** packaging of this file. Please review the following information to
22** ensure the GNU Lesser General Public License version 3 requirements
23** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
24**
25** GNU General Public License Usage
26** Alternatively, this file may be used under the terms of the GNU
27** General Public License version 2.0 or (at your option) the GNU General
28** Public license version 3 or any later version approved by the KDE Free
29** Qt Foundation. The licenses are as published by the Free Software
30** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
31** included in the packaging of this file. Please review the following
32** information to ensure the GNU General Public License requirements will
33** be met: https://www.gnu.org/licenses/gpl-2.0.html and
34** https://www.gnu.org/licenses/gpl-3.0.html.
35**
36** $QT_END_LICENSE$
37**
38****************************************************************************/
39
40#if !defined(QMETAOBJECT_P_H) && !defined(UTILS_H)
41# error "Include qmetaobject_p.h (or moc's utils.h) before including this file."
42#endif
43
44//
45// W A R N I N G
46// -------------
47//
48// This file is not part of the Qt API. It exists purely as an
49// implementation detail. This header file may change from version to
50// version without notice, or even be removed.
51//
52// We mean it.
53//
54
55#include <QtCore/private/qglobal_p.h>
56
57QT_BEGIN_NAMESPACE
58
59// This function is shared with moc.cpp. This file should be included where needed.
60static QByteArray normalizeTypeInternal(const char *t, const char *e, bool fixScope = false, bool adjustConst = true)
61{
62 int len = e - t;
63 /*
64 Convert 'char const *' into 'const char *'. Start at index 1,
65 not 0, because 'const char *' is already OK.
66 */
67 QByteArray constbuf;
68 for (int i = 1; i < len; i++) {
69 if ( t[i] == 'c'
70 && strncmp(s1: t + i + 1, s2: "onst", n: 4) == 0
71 && (i + 5 >= len || !is_ident_char(s: t[i + 5]))
72 && !is_ident_char(s: t[i-1])
73 ) {
74 constbuf = QByteArray(t, len);
75 if (is_space(s: t[i-1]))
76 constbuf.remove(index: i-1, len: 6);
77 else
78 constbuf.remove(index: i, len: 5);
79 constbuf.prepend(s: "const ");
80 t = constbuf.data();
81 e = constbuf.data() + constbuf.length();
82 break;
83 }
84 /*
85 We mustn't convert 'char * const *' into 'const char **'
86 and we must beware of 'Bar<const Bla>'.
87 */
88 if (t[i] == '&' || t[i] == '*' ||t[i] == '<')
89 break;
90 }
91 if (adjustConst && e > t + 6 && strncmp(s1: "const ", s2: t, n: 6) == 0) {
92 if (*(e-1) == '&') { // treat const reference as value
93 t += 6;
94 --e;
95 } else if (is_ident_char(s: *(e-1)) || *(e-1) == '>') { // treat const value as value
96 t += 6;
97 }
98 }
99 QByteArray result;
100 result.reserve(asize: len);
101
102#if 1
103 // consume initial 'const '
104 if (strncmp(s1: "const ", s2: t, n: 6) == 0) {
105 t+= 6;
106 result += "const ";
107 }
108#endif
109
110 // some type substitutions for 'unsigned x'
111 if (strncmp(s1: "unsigned", s2: t, n: 8) == 0) {
112 // make sure "unsigned" is an isolated word before making substitutions
113 if (!t[8] || !is_ident_char(s: t[8])) {
114 if (strncmp(s1: " int", s2: t+8, n: 4) == 0) {
115 t += 8+4;
116 result += "uint";
117 } else if (strncmp(s1: " long", s2: t+8, n: 5) == 0) {
118 if ((strlen(s: t + 8 + 5) < 4 || strncmp(s1: t + 8 + 5, s2: " int", n: 4) != 0) // preserve '[unsigned] long int'
119 && (strlen(s: t + 8 + 5) < 5 || strncmp(s1: t + 8 + 5, s2: " long", n: 5) != 0) // preserve '[unsigned] long long'
120 ) {
121 t += 8+5;
122 result += "ulong";
123 }
124 } else if (strncmp(s1: " short", s2: t+8, n: 6) != 0 // preserve unsigned short
125 && strncmp(s1: " char", s2: t+8, n: 5) != 0) { // preserve unsigned char
126 // treat rest (unsigned) as uint
127 t += 8;
128 result += "uint";
129 }
130 }
131 } else {
132 // discard 'struct', 'class', and 'enum'; they are optional
133 // and we don't want them in the normalized signature
134 struct {
135 const char *keyword;
136 int len;
137 } optional[] = {
138 { .keyword: "struct ", .len: 7 },
139 { .keyword: "class ", .len: 6 },
140 { .keyword: "enum ", .len: 5 },
141 { .keyword: nullptr, .len: 0 }
142 };
143 int i = 0;
144 do {
145 if (strncmp(s1: optional[i].keyword, s2: t, n: optional[i].len) == 0) {
146 t += optional[i].len;
147 break;
148 }
149 } while (optional[++i].keyword != nullptr);
150 }
151
152 bool star = false;
153 while (t != e) {
154 char c = *t++;
155 if (fixScope && c == ':' && *t == ':' ) {
156 ++t;
157 c = *t++;
158 int i = result.size() - 1;
159 while (i >= 0 && is_ident_char(s: result.at(i)))
160 --i;
161 result.resize(size: i + 1);
162 }
163 star = star || c == '*';
164 result += c;
165 if (c == '<') {
166 //template recursion
167 const char* tt = t;
168 int templdepth = 1;
169 int scopeDepth = 0;
170 while (t != e) {
171 c = *t++;
172 if (c == '{' || c == '(' || c == '[')
173 ++scopeDepth;
174 if (c == '}' || c == ')' || c == ']')
175 --scopeDepth;
176 if (scopeDepth == 0) {
177 if (c == '<')
178 ++templdepth;
179 if (c == '>')
180 --templdepth;
181 if (templdepth == 0 || (templdepth == 1 && c == ',')) {
182 result += normalizeTypeInternal(t: tt, e: t-1, fixScope, adjustConst: false);
183 result += c;
184 if (templdepth == 0) {
185 if (*t == '>')
186 result += ' '; // avoid >>
187 break;
188 }
189 tt = t;
190 }
191 }
192 }
193 }
194
195 // cv qualifers can appear after the type as well
196 if (!is_ident_char(s: c) && t != e && (e - t >= 5 && strncmp(s1: "const", s2: t, n: 5) == 0)
197 && (e - t == 5 || !is_ident_char(s: t[5]))) {
198 t += 5;
199 while (t != e && is_space(s: *t))
200 ++t;
201 if (adjustConst && t != e && *t == '&') {
202 // treat const ref as value
203 ++t;
204 } else if (adjustConst && !star) {
205 // treat const as value
206 } else if (!star) {
207 // move const to the front (but not if const comes after a *)
208 result.prepend(s: "const ");
209 } else {
210 // keep const after a *
211 result += "const";
212 }
213 }
214 }
215
216 return result;
217}
218
219QT_END_NAMESPACE
220

source code of qtbase/src/corelib/kernel/qmetaobject_moc_p.h