0

我的程序包含自动生成的结构。开始时,我需要使用“服务器”信息来验证它们——所以我可以确定我的自动生成的结构是最新的。如果服务器和本地结构具有相同的大小,包含具有相同名称和大小的字段(理想情况下也应该验证类型),则它们是有效的。

这是我到目前为止写的:

void SchemeValidator::Validate(cg_scheme_desc_t* schemedesc, Logger& logger)
{
    struct cg_message_desc_t* msgdesc = schemedesc->messages;
    while (msgdesc)
    {
        struct cg_field_desc_t* fielddesc = msgdesc->fields;
        char* structName = msgdesc->name;
        size_t structSize = msgdesc->size;
        logger.Debug("Message %s, block size = %d", structName, structSize);
        if (strcmp(structName, "orders")) {
            if (sizeof(orders) != structSize) {
                printf("Validator error, structure 'orders', local size = %d server size = %d!", sizeof(orders), structSize);
                throw std::exception("Validator error, structure 'orders' wrong size!");
            }
            while (fielddesc)
            {
                logger.Debug("\tField %s = %s [size=%d, offset=%d]", fielddesc->name, fielddesc->type, fielddesc->size, fielddesc->offset);
                if (offsetof(struct orders, fielddesc->name) != fielddesc->offset) {
                    throw std::exception("orders structure offset wrong");
                }
                // TODO: validate fielddesc->size == sizeof corresponding field in structure
                fielddesc = fielddesc->next;
            }
        } else {
            throw std::exception("Validator error, validation not implemented!");
        }

        msgdesc = msgdesc->next;
    }
}

有很多问题:

我写if (strcmp(structName, "orders"))是因为后来我需要orders在几个表达式中使用,包括sizeof(orders)and offsetof(struct orders, fielddesc->name)。但是我有很多结构,对于每个结构,我都必须复制粘贴这个块。我可以以某种方式将字符串文字传递给sizeofandoffsetof方法或以其他方式获得预期的效果吗?

offsetof(struct orders, fielddesc->name)由于同样的原因不起作用 - 第二个参数不能是字符串文字,我收到error C2039: 'fielddesc' : is not a member of 'orders'错误

出于同样的原因,我可以验证fielddesc->size.

如何在不进行大量复制粘贴和值硬编码的情况下实现所需的验证?

4

1 回答 1

0

我相信您可以通过使用 typedef 定义结构并使用模板化函数来完成您想要的。以下内容应替换您拥有的内容(显然未经测试)

struct OrderType {
   typedef cg_field_desc_t* ListItem;
   typedef orders           Class;
   static const std::string Name;
};

std::string OrderType::Name = "orders";

template <class T>
checkStuff(T::ListItem fielddesc, const char* name, size_t structSize)
{
   if (strcmp(name, T::Name.c_str())) {
      if (sizeof(T::Class) != structSize) {
         printf("Validator error, structure 'orders', local size = %d server size = %d!", sizeof(T::Class), structSize);
         throw std::exception("Validator error, structure 'orders' wrong size!");
      }
      while (fielddesc)
      {
         logger.Debug("\tField %s = %s [size=%d, offset=%d]", fielddesc->name, fielddesc->type, fielddesc->size, fielddesc->offset);
         if (offsetof(T::Class, fielddesc->name) != fielddesc->offset) {
            throw std::exception("orders structure offset wrong");
         }
         // TODO: validate fielddesc->size == sizeof corresponding field in structure
         fielddesc = fielddesc->next;
      }
   } else {
      throw std::exception("Validator error, validation not implemented!");
   }
}

然后,您将 if 语句替换为

checkStuff<OrderType>(fielddesc, name, structSize);

您可以通过定义新结构将其扩展到其他类型

struct OtherType {
   typedef some_other_t*    ListItem;
   typedef bizbaz           Class;
   static const std::string Name;
};

std::string OtherType::Name = "foobar";
于 2013-06-23T00:59:13.777 回答