diff options
Diffstat (limited to 'generator/shiboken2/shibokennormalize.cpp')
-rw-r--r-- | generator/shiboken2/shibokennormalize.cpp | 274 |
1 files changed, 274 insertions, 0 deletions
diff --git a/generator/shiboken2/shibokennormalize.cpp b/generator/shiboken2/shibokennormalize.cpp new file mode 100644 index 0000000..aafb451 --- /dev/null +++ b/generator/shiboken2/shibokennormalize.cpp @@ -0,0 +1,274 @@ +/* + * This file is part of the PySide project. + * This code was extracted from qmetaobject_p.h present on Qt4.7. + * + * Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). + * + * Contact: PySide team <contact@pyside.org> + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "shibokennormalize_p.h" +#include <QVarLengthArray> + +#if (QT_VERSION < QT_VERSION_CHECK(4, 7, 0)) + +// mirrored in moc's utils.h +static inline bool is_ident_char(char s) +{ + return ((s >= 'a' && s <= 'z') + || (s >= 'A' && s <= 'Z') + || (s >= '0' && s <= '9') + || s == '_' + ); +} + +static inline bool is_space(char s) +{ + return (s == ' ' || s == '\t'); +} + +static void qRemoveWhitespace(const char *s, char *d) +{ + char last = 0; + while (*s && is_space(*s)) + s++; + while (*s) { + while (*s && !is_space(*s)) + last = *d++ = *s++; + while (*s && is_space(*s)) + s++; + if (*s && ((is_ident_char(*s) && is_ident_char(last)) + || ((*s == ':') && (last == '<')))) { + last = *d++ = ' '; + } + } + *d = '\0'; +} + +// This code is shared with moc.cpp +static QByteArray normalizeTypeInternalQt47(const char *t, const char *e, bool fixScope = false, bool adjustConst = true) +{ + int len = e - t; + /* + Convert 'char const *' into 'const char *'. Start at index 1, + not 0, because 'const char *' is already OK. + */ + QByteArray constbuf; + for (int i = 1; i < len; i++) { + if ( t[i] == 'c' + && strncmp(t + i + 1, "onst", 4) == 0 + && (i + 5 >= len || !is_ident_char(t[i + 5])) + && !is_ident_char(t[i-1]) + ) { + constbuf = QByteArray(t, len); + if (is_space(t[i-1])) + constbuf.remove(i-1, 6); + else + constbuf.remove(i, 5); + constbuf.prepend("const "); + t = constbuf.data(); + e = constbuf.data() + constbuf.length(); + break; + } + /* + We musn't convert 'char * const *' into 'const char **' + and we must beware of 'Bar<const Bla>'. + */ + if (t[i] == '&' || t[i] == '*' ||t[i] == '<') + break; + } + if (adjustConst && e > t + 6 && strncmp("const ", t, 6) == 0) { + if (*(e-1) == '&') { // treat const reference as value + t += 6; + --e; + } else if (is_ident_char(*(e-1)) || *(e-1) == '>') { // treat const value as value + t += 6; + } + } + QByteArray result; + result.reserve(len); + +#if 1 + // consume initial 'const ' + if (strncmp("const ", t, 6) == 0) { + t+= 6; + result += "const "; + } +#endif + + // some type substitutions for 'unsigned x' + if (strncmp("unsigned", t, 8) == 0) { + // make sure "unsigned" is an isolated word before making substitutions + if (!t[8] || !is_ident_char(t[8])) { + if (strncmp(" int", t+8, 4) == 0) { + t += 8+4; + result += "uint"; + } else if (strncmp(" long", t+8, 5) == 0) { + if ((strlen(t + 8 + 5) < 4 || strncmp(t + 8 + 5, " int", 4) != 0) // preserve '[unsigned] long int' + && (strlen(t + 8 + 5) < 5 || strncmp(t + 8 + 5, " long", 5) != 0) // preserve '[unsigned] long long' + ) { + t += 8+5; + result += "ulong"; + } + } else if (strncmp(" short", t+8, 6) != 0 // preserve unsigned short + && strncmp(" char", t+8, 5) != 0) { // preserve unsigned char + // treat rest (unsigned) as uint + t += 8; + result += "uint"; + } + } + } else { + // discard 'struct', 'class', and 'enum'; they are optional + // and we don't want them in the normalized signature + struct { + const char *keyword; + int len; + } optional[] = { + { "struct ", 7 }, + { "class ", 6 }, + { "enum ", 5 }, + { 0, 0 } + }; + int i = 0; + do { + if (strncmp(optional[i].keyword, t, optional[i].len) == 0) { + t += optional[i].len; + break; + } + } while (optional[++i].keyword != 0); + } + + bool star = false; + while (t != e) { + char c = *t++; + if (fixScope && c == ':' && *t == ':' ) { + ++t; + c = *t++; + int i = result.size() - 1; + while (i >= 0 && is_ident_char(result.at(i))) + --i; + result.resize(i + 1); + } + star = star || c == '*'; + result += c; + if (c == '<') { + //template recursion + const char* tt = t; + int templdepth = 1; + while (t != e) { + c = *t++; + if (c == '<') + ++templdepth; + if (c == '>') + --templdepth; + if (templdepth == 0 || (templdepth == 1 && c == ',')) { + result += normalizeTypeInternalQt47(tt, t-1, fixScope, false); + result += c; + if (templdepth == 0) { + if (*t == '>') + result += ' '; // avoid >> + break; + } + tt = t; + } + } + } + + // cv qualifers can appear after the type as well + if (!is_ident_char(c) && t != e && (e - t >= 5 && strncmp("const", t, 5) == 0) + && (e - t == 5 || !is_ident_char(t[5]))) { + t += 5; + while (t != e && is_space(*t)) + ++t; + if (adjustConst && t != e && *t == '&') { + // treat const ref as value + ++t; + } else if (adjustConst && !star) { + // treat const as value + } else if (!star) { + // move const to the front (but not if const comes after a *) + result.prepend("const "); + } else { + // keep const after a * + result += "const"; + } + } + } + + return result; +} + +static char *qNormalizeTypeQt47(char *d, int &templdepth, QByteArray &result) +{ + const char *t = d; + while (*d && (templdepth + || (*d != ',' && *d != ')'))) { + if (*d == '<') + ++templdepth; + if (*d == '>') + --templdepth; + ++d; + } + if (strncmp("void", t, d - t) != 0) + result += normalizeTypeInternalQt47(t, d); + + return d; +} + + +QByteArray QMetaObject_normalizedTypeQt47(const char *type) +{ + QByteArray result; + + if (!type || !*type) + return result; + + QVarLengthArray<char> stackbuf(qstrlen(type) + 1); + qRemoveWhitespace(type, stackbuf.data()); + int templdepth = 0; + qNormalizeTypeQt47(stackbuf.data(), templdepth, result); + + return result; +} + +QByteArray QMetaObject_normalizedSignatureQt47(const char *method) +{ + QByteArray result; + if (!method || !*method) + return result; + int len = int(strlen(method)); + QVarLengthArray<char> stackbuf(len + 1); + char *d = stackbuf.data(); + qRemoveWhitespace(method, d); + + result.reserve(len); + + int argdepth = 0; + int templdepth = 0; + while (*d) { + if (argdepth == 1) + d = qNormalizeTypeQt47(d, templdepth, result); + if (*d == '(') + ++argdepth; + if (*d == ')') + --argdepth; + result += *d++; + } + + return result; +} +#endif |