c++ - 表示命令包格式的数据结构
问题描述
我的目的是构建一个配置文件。所以我基本上必须以某种方式表示命令包结构。
当实际数据(二进制)出现时,我想将数据包与此配置文件进行比较,然后对其进行处理(将数据转换为 CSV 格式)。
所以有不同的命令类型。
所以每次收到一个数据包时,我都必须获取它的操作码并用配置文件检查它,并返回代表该数据包格式的适当命令格式。
命令格式可能如下所示:
操作码 - 1 个字节 - 整数
命令 - 4 字节 - 字符串
...
所有命令都没有相同数量的字段或相同的格式。
我想检索所有这些细节。我可以用 XML 表示它并使用 libxml2 之类的库对其进行解析。
下面给出了一个示例 XML 格式:
<cmd type="Multiplication">
<field name="opcode" type="string" bytes="4"/>
<field name="Multiplicand" type="number" bytes="2"/>
<field name="Multiplier" type="number" bytes="2"/>
</cmd>
但这种方法相当缓慢。
我的想法是以某种方式在结构中表示命令包格式。但是由于 C/C++ 不是一种反射语言,因此无法知道结构成员,并且每个结构(命令)都需要一个函数来解析它。
请提出一些存储格式的方法,这样一个通用函数就可以通过查看这种格式来解析二进制数据。
- 语言可以是 C 或 C++。
- 性能是重中之重,因此不鼓励使用 XML 和类似类型。
- 在内存中数据结构是首选。
非常感谢任何帮助。
解决方案
我认为您最好的选择是将文件表示为variant
正确命令类型的 s 的集合。例如,假设您有三个命令选项:
struct Constant {
short value;
};
struct UnaryOperation {
unsigned char opcode;
short value;
};
struct BinaryOperation {
unsigned char opcode;
short value1;
short value2;
};
表示未知命令。如果你有一个未知的命令,你可以将它表示为variant
三种类型中的一种:
using Command = std::variant<Constant, UnaryOperation, BinaryOperation>;
根据命令类型应用函数。假设每个命令都有不同的功能:
short eval(Constant c) {
return c.value;
}
short eval(UnaryOperation u) {
switch(u.opcode) {
// stuff
}
}
short eval(BinaryOperation b) {
switch(b.opcode) {
// stuff
}
}
我们可以std::visit
用来评估一个任意的Command
:
short evaluate_command(Command const& command) {
short output;
// This calls the right overload automatically
std::visit(command, [&](auto cmd) { output = eval(cmd); });
return output;
}
解析命令。
我们可以从它定义的任何类型中自动创建一个std::variant
。这意味着,如果您提供一种方法来确定基于文件的命令是什么,那么这很容易做到。
enum class OpType : unsigned char {
ConstantOp, UnaryOp, BinaryOp
};
// Command can be automatically constructed from a Constant, a UnaryOperation, or a BinaryOperation
Command readFromStream(std::istream& i) {
OpType type;
unsigned char op;
short value, value2;
// Read the type of the operation
i >> (unsigned char&)type;
//Return either a Constant, a UnaryOperation, or a BinaryOperation
switch(type) {
case OpType::ConstantOp: {
i >> value;
return Constant{value};
}
case OpType::UnaryOp: {
i >> op >> value;
return UnaryOperation{op, value};
}
case OpType::BinaryOp {
i >> op >> value >> value2;
return BinaryOperation{op, value, value2};
}
}
}
推荐阅读
- amp-html - 如何使用 amp-iframe 进行地理定位?
- c++ - 我需要使用内联关键字吗?
- python - mysql 每个 id/name 返回 1 行
- alexa-skills-kit - Amazon Alexa Entity Resolutions:是否可以有多个 AuthoritiesPerResolution?
- java - Swagger:如何注释映射到字符串的对象
- ruby-on-rails - 数据未存储在表导轨中
- c - Makefile .c + .as 与 ncurses
- javascript - 动态插入两个 div 时未应用 nth-child 选择器
- php - 根据商店存档页面验证 woocommerce 购物车
- ruby-on-rails - 发送和接收激活电子邮件 - michael hartl 的 ruby on rails 教程