验证结构-如何将字符串传递给sizeof和offset方法

validating structures - how to pass string to sizeof and offset methods?

本文关键字:sizeof 方法 offset 字符串 结构 验证      更新时间:2023-10-16

我的程序包含自动生成的结构。在开始时,我需要用"服务器"信息来验证它们,这样我就可以确保我自动生成的结构是最新的。如果服务器和本地结构具有相同的大小,并且包含具有相同名称和大小的字段(理想情况下还应验证类型),则它们是有效的。

这是我迄今为止写的:

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)offsetof(struct orders, fielddesc->name)。但我有很多结构,每一个我都必须复制粘贴这个块。我可以以某种方式将字符串文本传递给sizeofoffsetof方法吗?或者以其他方式产生所需的效果吗?

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

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

如何在没有密集的复制粘贴和值硬编码的情况下实现所需的验证?

我相信您可以通过用typedefs定义结构并使用模板化函数来实现您想要的。以下内容应取代您的(显然未经测试)

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";