c++ - 使用 TinyCbor C 库对 uint8_t 进行编码和解码
问题描述
我正在实现基于 C++ 11 的应用程序,并且我正在使用TinyCbor C 库对应用程序特定数据进行编码和解码,如下所示:
#include "cbor.h"
#include <iostream>
using namespace std;
int main() {
struct MyTest {
uint8_t varA;
float vabB;
};
MyTest obj;
obj.varA = 100; // If I set it t0 below 20 then it works
obj.varB = 10.10;
uint8_t buff[100];
//Encode
CborEncode encoder;
CborEncode array;
cbor_encoder_init(&encoder, buff, sizeof(buff), 0);
cbor_encoder_create_array(&encode, &array, CborIndefiniteLength);
cbor_encode_simple_value(&array, obj.varA);
cbor_encode_float(&array, obj.varB);
cbor_encoder_close_container(&encoder, &array);
// Decode
CborParser parse;
CborValue value;
cbor_parser_init(buff, sizeof(buff), 0, &parser, &value);
CborValue array;
cbor_value_enter_container(&value, &array);
uint8_t val;
cbor_value_get_simple_type(&array, &val);
// This prints blank
cout << "uint8_t value: " << static_cast<int>(val) << endl;
float fval;
cbor_value_get_simple_type(&array, &fval);
cout << "float value: " << fval << endl;
return 0;
}
当我将值设置uint8_t varA
为低于 20 时,上面的代码有效,我看到 20 打印在控制台上,但如果我设置超过 20,那么有时它会给出错误CborErrorIllegalSimpleType
。或者如果 value 设置为21
then 它返回我的类型为CborBooleanType
or CborNullType
。
代码有什么问题
如何
uint8_t
使用 TinyCbor 进行编码和解码。
解决方案
你有一些事情发生在这里。
cbor_encoder_create_array(&encode, &array, CborIndefinedLength);
除非您计划流式传输编码,否则不要使用无限长度。如果在编码时您面前有所有数据,请使用定义的长度。在这里了解原因:也将固定大小的 Map 序列化为 CBOR ,我不确定您使用的是什么版本,但不确定长度的对象至少最近是 TinyCBOR 的 TO DO 列表项。
cbor_value_get_simple_type(&array, &val);
这里不需要简单。简单类型是基本未定义的基本类型。CBOR 的默认类型是 int64_t,signed long long。Simple 确实允许在 8bit 处自然停止,但 simple 中的 20 是 Boolean false。21 为真,22 为空。你已经发现了这一点。它不能存储负数或浮点数,虽然你可以用它来表示像“100”这样的 8 位,但你真的不应该。关于 CBOR 类型的好消息是,虽然默认值为 64 位,但它使用尽可能少的内存进行编码。所以在 CBOR 中存储 100 是一个字节,而不是 8 个,不计算一秒钟的开销。编辑:澄清,2 个字节存储整数 100。CBOR 是 0-23 的一个字节,但 24 和一个有一个字节的开销。
开销我的意思是,当你编码一个 cbor 整数时,前三位表示 UNSIGNED INTEGER(二进制 000),一位是保留的,其他 4 位是值,所以如果你有一个适合这四位的小值(值 0-23)你可以在一个字节中得到它。该保留位很奇怪,请参阅此处的图表以了解它:https : //en.m.wikipedia.org/wiki/CBOR 所以 24-255 需要 2 个字节编码,等等。与它总是使用 8 个字节相去甚远。因为它可以。
这里的简短版本是 CBOR 不会使用比需要更多的空间 - 但是 - 它不是强类型序列化程序!如果您的意思是将 100 个 8 位内部存储在该数组中,并且有人将 10000 个存储在 16 位中,那么在您解析并在 8 位点中存储大量数字之前,它看起来/工作正常。您需要转换或验证您的数据。我建议解析然后验证。
cbor_value_get_simple_type(&array, &fval);
cout << "浮点值:" << fval << endl;
我必须查看 TinyCBOR 的代码,但我认为这是一个快乐的意外,并且在技术上不支持工作。因为简单类型使用相同的三个主要位,所以您可以使用 get_simple 获得值的 64 位精度。相反,您应该检查类型并正确调用获取全精度或半精度浮点数。
TinyCBOR 相当不错,但肯定隐藏了一些陷阱。即使您相信序列化程序会为您完成工作,理解 CBOR 编码也确实很有帮助。
推荐阅读
- google-apps-script - Google 表单的链接列表以列出 Google 表格
- powershell - 使用powershell获取“Audit Policy”安全设置值
- php - 我可以在 Ubuntu Server 20.04 上使用 PHP 5.3.29 安装 apache 吗?
- go - 转到列表:查询“最新”没有匹配的版本
- kotlin - 有没有像 Python 的 RICH 一样的库,但适用于 Kotlin?
- javascript - “可选”字段的字段验证
- java - 当请求被客户端中止时,WebFlux 如何停止发布者?
- kubernetes - Helm,K8s:是否可以将 k8s 机密中的值提取到 configmap.yaml
- html - 在烧瓶中验证 reCAPTCHA
- c# - 如何从包含 .Net 5 Web API 中的 HttpContext 数据的通用类创建响应