PageRenderTime 45ms CodeModel.GetById 17ms RepoModel.GetById 0ms app.codeStats 0ms

/generator/shiboken/shibokennormalize.cpp

https://github.com/PySide/Shiboken
C++ | 274 lines | 208 code | 22 blank | 44 comment | 150 complexity | 702bc69229c08129901c0aa9df64a8bc MD5 | raw file
Possible License(s): LGPL-2.1, BSD-3-Clause, GPL-2.0
  1. /*
  2. * This file is part of the PySide project.
  3. * This code was extracted from qmetaobject_p.h present on Qt4.7.
  4. *
  5. * Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
  6. *
  7. * Contact: PySide team <contact@pyside.org>
  8. *
  9. * This library is free software; you can redistribute it and/or
  10. * modify it under the terms of the GNU Lesser General Public
  11. * License as published by the Free Software Foundation; either
  12. * version 2.1 of the License, or (at your option) any later version.
  13. *
  14. * This library is distributed in the hope that it will be useful,
  15. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  16. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  17. * Lesser General Public License for more details.
  18. *
  19. * You should have received a copy of the GNU Lesser General Public
  20. * License along with this library; if not, write to the Free Software
  21. * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
  22. */
  23. #include "shibokennormalize_p.h"
  24. #include <QVarLengthArray>
  25. #if (QT_VERSION < QT_VERSION_CHECK(4, 7, 0))
  26. // mirrored in moc's utils.h
  27. static inline bool is_ident_char(char s)
  28. {
  29. return ((s >= 'a' && s <= 'z')
  30. || (s >= 'A' && s <= 'Z')
  31. || (s >= '0' && s <= '9')
  32. || s == '_'
  33. );
  34. }
  35. static inline bool is_space(char s)
  36. {
  37. return (s == ' ' || s == '\t');
  38. }
  39. static void qRemoveWhitespace(const char *s, char *d)
  40. {
  41. char last = 0;
  42. while (*s && is_space(*s))
  43. s++;
  44. while (*s) {
  45. while (*s && !is_space(*s))
  46. last = *d++ = *s++;
  47. while (*s && is_space(*s))
  48. s++;
  49. if (*s && ((is_ident_char(*s) && is_ident_char(last))
  50. || ((*s == ':') && (last == '<')))) {
  51. last = *d++ = ' ';
  52. }
  53. }
  54. *d = '\0';
  55. }
  56. // This code is shared with moc.cpp
  57. static QByteArray normalizeTypeInternalQt47(const char *t, const char *e, bool fixScope = false, bool adjustConst = true)
  58. {
  59. int len = e - t;
  60. /*
  61. Convert 'char const *' into 'const char *'. Start at index 1,
  62. not 0, because 'const char *' is already OK.
  63. */
  64. QByteArray constbuf;
  65. for (int i = 1; i < len; i++) {
  66. if ( t[i] == 'c'
  67. && strncmp(t + i + 1, "onst", 4) == 0
  68. && (i + 5 >= len || !is_ident_char(t[i + 5]))
  69. && !is_ident_char(t[i-1])
  70. ) {
  71. constbuf = QByteArray(t, len);
  72. if (is_space(t[i-1]))
  73. constbuf.remove(i-1, 6);
  74. else
  75. constbuf.remove(i, 5);
  76. constbuf.prepend("const ");
  77. t = constbuf.data();
  78. e = constbuf.data() + constbuf.length();
  79. break;
  80. }
  81. /*
  82. We musn't convert 'char * const *' into 'const char **'
  83. and we must beware of 'Bar<const Bla>'.
  84. */
  85. if (t[i] == '&' || t[i] == '*' ||t[i] == '<')
  86. break;
  87. }
  88. if (adjustConst && e > t + 6 && strncmp("const ", t, 6) == 0) {
  89. if (*(e-1) == '&') { // treat const reference as value
  90. t += 6;
  91. --e;
  92. } else if (is_ident_char(*(e-1)) || *(e-1) == '>') { // treat const value as value
  93. t += 6;
  94. }
  95. }
  96. QByteArray result;
  97. result.reserve(len);
  98. #if 1
  99. // consume initial 'const '
  100. if (strncmp("const ", t, 6) == 0) {
  101. t+= 6;
  102. result += "const ";
  103. }
  104. #endif
  105. // some type substitutions for 'unsigned x'
  106. if (strncmp("unsigned", t, 8) == 0) {
  107. // make sure "unsigned" is an isolated word before making substitutions
  108. if (!t[8] || !is_ident_char(t[8])) {
  109. if (strncmp(" int", t+8, 4) == 0) {
  110. t += 8+4;
  111. result += "uint";
  112. } else if (strncmp(" long", t+8, 5) == 0) {
  113. if ((strlen(t + 8 + 5) < 4 || strncmp(t + 8 + 5, " int", 4) != 0) // preserve '[unsigned] long int'
  114. && (strlen(t + 8 + 5) < 5 || strncmp(t + 8 + 5, " long", 5) != 0) // preserve '[unsigned] long long'
  115. ) {
  116. t += 8+5;
  117. result += "ulong";
  118. }
  119. } else if (strncmp(" short", t+8, 6) != 0 // preserve unsigned short
  120. && strncmp(" char", t+8, 5) != 0) { // preserve unsigned char
  121. // treat rest (unsigned) as uint
  122. t += 8;
  123. result += "uint";
  124. }
  125. }
  126. } else {
  127. // discard 'struct', 'class', and 'enum'; they are optional
  128. // and we don't want them in the normalized signature
  129. struct {
  130. const char *keyword;
  131. int len;
  132. } optional[] = {
  133. { "struct ", 7 },
  134. { "class ", 6 },
  135. { "enum ", 5 },
  136. { 0, 0 }
  137. };
  138. int i = 0;
  139. do {
  140. if (strncmp(optional[i].keyword, t, optional[i].len) == 0) {
  141. t += optional[i].len;
  142. break;
  143. }
  144. } while (optional[++i].keyword != 0);
  145. }
  146. bool star = false;
  147. while (t != e) {
  148. char c = *t++;
  149. if (fixScope && c == ':' && *t == ':' ) {
  150. ++t;
  151. c = *t++;
  152. int i = result.size() - 1;
  153. while (i >= 0 && is_ident_char(result.at(i)))
  154. --i;
  155. result.resize(i + 1);
  156. }
  157. star = star || c == '*';
  158. result += c;
  159. if (c == '<') {
  160. //template recursion
  161. const char* tt = t;
  162. int templdepth = 1;
  163. while (t != e) {
  164. c = *t++;
  165. if (c == '<')
  166. ++templdepth;
  167. if (c == '>')
  168. --templdepth;
  169. if (templdepth == 0 || (templdepth == 1 && c == ',')) {
  170. result += normalizeTypeInternalQt47(tt, t-1, fixScope, false);
  171. result += c;
  172. if (templdepth == 0) {
  173. if (*t == '>')
  174. result += ' '; // avoid >>
  175. break;
  176. }
  177. tt = t;
  178. }
  179. }
  180. }
  181. // cv qualifers can appear after the type as well
  182. if (!is_ident_char(c) && t != e && (e - t >= 5 && strncmp("const", t, 5) == 0)
  183. && (e - t == 5 || !is_ident_char(t[5]))) {
  184. t += 5;
  185. while (t != e && is_space(*t))
  186. ++t;
  187. if (adjustConst && t != e && *t == '&') {
  188. // treat const ref as value
  189. ++t;
  190. } else if (adjustConst && !star) {
  191. // treat const as value
  192. } else if (!star) {
  193. // move const to the front (but not if const comes after a *)
  194. result.prepend("const ");
  195. } else {
  196. // keep const after a *
  197. result += "const";
  198. }
  199. }
  200. }
  201. return result;
  202. }
  203. static char *qNormalizeTypeQt47(char *d, int &templdepth, QByteArray &result)
  204. {
  205. const char *t = d;
  206. while (*d && (templdepth
  207. || (*d != ',' && *d != ')'))) {
  208. if (*d == '<')
  209. ++templdepth;
  210. if (*d == '>')
  211. --templdepth;
  212. ++d;
  213. }
  214. if (strncmp("void", t, d - t) != 0)
  215. result += normalizeTypeInternalQt47(t, d);
  216. return d;
  217. }
  218. QByteArray QMetaObject_normalizedTypeQt47(const char *type)
  219. {
  220. QByteArray result;
  221. if (!type || !*type)
  222. return result;
  223. QVarLengthArray<char> stackbuf(qstrlen(type) + 1);
  224. qRemoveWhitespace(type, stackbuf.data());
  225. int templdepth = 0;
  226. qNormalizeTypeQt47(stackbuf.data(), templdepth, result);
  227. return result;
  228. }
  229. QByteArray QMetaObject_normalizedSignatureQt47(const char *method)
  230. {
  231. QByteArray result;
  232. if (!method || !*method)
  233. return result;
  234. int len = int(strlen(method));
  235. QVarLengthArray<char> stackbuf(len + 1);
  236. char *d = stackbuf.data();
  237. qRemoveWhitespace(method, d);
  238. result.reserve(len);
  239. int argdepth = 0;
  240. int templdepth = 0;
  241. while (*d) {
  242. if (argdepth == 1)
  243. d = qNormalizeTypeQt47(d, templdepth, result);
  244. if (*d == '(')
  245. ++argdepth;
  246. if (*d == ')')
  247. --argdepth;
  248. result += *d++;
  249. }
  250. return result;
  251. }
  252. #endif