首页 > 解决方案 > 使用 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 设置为21then 它返回我的类型为CborBooleanTypeor CborNullType

  1. 代码有什么问题

  2. 如何uint8_t使用 TinyCbor 进行编码和解码。

标签: c++cuint8tcbor

解决方案


你有一些事情发生在这里。

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 编码也确实很有帮助。


推荐阅读