QT实现(3)

6 篇文章 0 订阅
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 == '_'
      );
}

函数主要将传进来的多余的空格字符非去掉,生成标准的可以处理的字符串。

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放在参数中间的情况。由于与操作的特性当地一个字符不等于c的时候,下面的就可以不做了,这样的话就加速了处理,另外如果i+5<length的时候,并且i+5是一个可识别的字符,那么整个表明const是字符参数的一部分。接下来遇到指针星号,取地址符号以及类别模板的左括号就终止是因为 const char *和char const *是一样的,所以这里的操作将这个const移到最前面去。但是char * const和上面两个是不同的(具体原因可见关于const的那篇博客)。接下来是具体类型的处理,当遇到struct之类的,实际不需要这些标识符在C++当中也能表达一个类别,接下来看看是否在某一个区域内——是否有::标识符标志区域,如果要求命名空间或者类别是固定的,那么直接将前面的命名空间或者类别去掉。接下来还要分析是否有内置的类型,也就是说可以有模板参数。如果有模板参数需要地柜处理,然后下一步分析后置的const,最后的else if和else表明是否为后置的const。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值