QByteArray QMetaObject::normalizedSignature(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 = qNormalizeType(d, templdepth, result);
if (!*d)
break;
}
if (*d == '(')
++argdepth;
if (*d == ')')
--argdepth;
result += *d++;
}
return result;
}
这个函数主要对QT信号和槽函数当中的参数,由while当中的if语句可以看出,信号函数只能有一个括号包含而不能出现强制类型转换(因为强制类型转换会使得出现两个括号)。当然出现两个括号本身编译可以通过,但是信号连接会有问题,并且在编译的时候会有相应的信息在编译输出部分进行提示。
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'; }
static inline bool is_ident_char(char s) { return ((s >= 'a' && s <= 'z') || (s >= 'A' && s <= 'Z') || (s >= '0' && s <= '9') || s == '_' ); }
函数主要将传进来的多余的空格字符非去掉,生成标准的可以处理的字符串。
利用循环分离出字符串,由于void和无参是一样的所以需要区别对待,由于参数的结尾符号是逗号或者括号,所以从这里也可以看出,在connect当中添加形参会引起connect错误,当然编译会通过,但是同样编译输出会有提示。static char *qNormalizeType(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 += normalizeTypeInternal(t, d); return d; }
由于const 可以放置的地方很多,所以第一个循环是为了得到const放在参数中间的情况。由于与操作的特性当地一个字符不等于c的时候,下面的就可以不做了,这样的话就加速了处理,另外如果i+5<length的时候,并且i+5是一个可识别的字符,那么整个表明const是字符参数的一部分。接下来遇到指针星号,取地址符号以及类别模板的左括号就终止是因为 const char *和char const *是一样的,所以这里的操作将这个const移到最前面去。但是char * const和上面两个是不同的(具体原因可见关于const的那篇博客)。接下来是具体类型的处理,当遇到struct之类的,实际不需要这些标识符在C++当中也能表达一个类别,接下来看看是否在某一个区域内——是否有::标识符标志区域,如果要求命名空间或者类别是固定的,那么直接将前面的命名空间或者类别去掉。接下来还要分析是否有内置的类型,也就是说可以有模板参数。如果有模板参数需要地柜处理,然后下一步分析后置的const,最后的else if和else表明是否为后置的const。static QByteArray normalizeTypeInternal(const char *t, const char *e, bool fixScope = false, bool adjustConst = true) { int len = e - t; 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; } if (t[i] == '&' || t[i] == '*' ||t[i] == '<') break; } if (adjustConst && e > t + 6 && strncmp("const ", t, 6) == 0) { if (*(e-1) == '&') { t += 6; --e; } else if (is_ident_char(*(e-1)) || *(e-1) == '>') { t += 6; } } QByteArray result; result.reserve(len); if (strncmp("const ", t, 6) == 0) { t+= 6; result += "const "; } if (strncmp("unsigned", t, 8) == 0) { 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)&& (strlen(t + 8 + 5) < 5 || strncmp(t + 8 + 5, " long", 5) != 0)) { t += 8+5; result += "ulong"; } } else if (strncmp(" short", t+8, 6) != 0&& strncmp(" char", t+8, 5) != 0) { t += 8; result += "uint"; } } } else { 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 == '<') { 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 += normalizeTypeInternal(tt, t-1, fixScope, false); result += c; if (templdepth == 0) { if (*t == '>') result += ' '; break; } tt = t; } } } 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 == '&') { ++t; } else if (adjustConst && !star) { } else if (!star) { result.prepend("const "); } else { result += "const"; } } } return result; }