QT実装(3)


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文から分かるように、信号関数は1つの括弧しか含まれず、強制タイプ変換は現れない(強制タイプ変換は2つの括弧が現れるため).もちろん、2つのカッコ自体のコンパイルは通過できますが、信号接続に問題があり、コンパイル時にコンパイル出力部に相応の情報が提示されます.
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 == '_'
      );
}

, 。

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;
}
はループを して を しているが,voidと パラメータは じであるため が であり,パラメータの はカンマや であるため,ここからもconnectにパラメータを するとconnectエラーを き こし, コンパイルは じるが, のコンパイル にヒントがあることがわかる.
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;
}
はconstが くことができる が いため、 のループはconstがパラメータの ん に かれている を るためである. の と で1 がcに しくない 、 は わなくてもよいので、 が し、またi+5ifとelseは、 のconstであるかどうかを します.