cbor的介绍及tinycbor的使用

1. cbor介绍

CBOR(Concise Binary Object Representation)是一种轻量级的数据交换格式,类似于JSON,但它以二进制形式表示数据,而不是文本形式。CBOR设计用于在网络上传输数据时减少数据的大小和复杂性,同时保持良好的可读性和可扩展性。

CBOR数据结构

CBOR数据结构是基于键值对(key-value pairs)的,这意味着数据可以被组织成一系列的键和它们对应的值。在CBOR中,键通常是字符串,而值可以是多种数据类型,包括:

  • 整数(正数、负数、零)
  • 字符串(UTF-8编码的文本)
  • 数组(有序的值列表)
  • 映射(无序的键值对集合)
  • 布尔值(true或false)
  • 空值(null)
  • 浮点数(单精度和双精度)
  • 二进制数据(字节数组)
  • 日期和时间(使用自定义的格式)

CBOR的表示方式

CBOR使用一系列的标记来表示不同的数据类型和值。例如,整数和字符串有特定的标记,而数组和映射则使用不同的标记。这种标记系统使得CBOR能够在不损失信息的情况下,以紧凑的方式表示复杂的数据结构。

CBOR的优势

  • 紧凑性:CBOR的二进制表示比文本格式(如JSON)更紧凑,减少了数据传输的大小。
  • 灵活性:CBOR支持多种数据类型,包括自定义类型,这使得它非常灵活,适用于各种应用场景。
  • 简单性:CBOR的编码和解码过程相对简单,不需要复杂的解析器。
  • 互操作性:CBOR可以很容易地与JSON等文本格式相互转换,便于与其他系统集成。

CBOR的应用

CBOR广泛应用于需要高效数据交换的场景,如物联网(IoT)设备之间的通信、嵌入式系统、以及任何需要减少数据传输量的网络应用。由于其紧凑性和灵活性,CBOR也被用于实现FIDO2认证协议中的数据交换,特别是在CTAP2(Client to Authenticator Protocol 2)中。

总之,CBOR是一种高效、灵活的数据表示格式,它以键值对的形式组织数据,适用于各种需要高效数据交换的场景。

2. tinycbor的使用

  • github地址:https://github.com/intel/tinycbor.git
  • 使用文档:https://intel.github.io/tinycbor/current/

示例程序一

// 创建一个简单的map
int test2()
{  
    // 分配足够的内存来存储CBOR编码的数据  
    // 注意:这个大小是估计的,实际大小可能更小或更大  
    // 你可以使用cbor_encoder_get_buffer_size来在编码后获取实际大小  
    uint8_t cbor_buffer[256];  
    size_t buffer_size = sizeof(cbor_buffer);  
  
    // 初始化编码器  
    CborEncoder encoder;  
    cbor_encoder_init(&encoder, cbor_buffer, buffer_size, 0);  
  
    // 开始一个映射(类似于JSON对象)  
    CborEncoder map_encoder;  
    cbor_encoder_create_map(&encoder, &map_encoder, CborIndefiniteLength);  
  
    // 添加键值对 "name": "John"  
    cbor_encode_text_stringz(&map_encoder, "name");  
    cbor_encode_text_stringz(&map_encoder, "John");  
  
    // 添加键值对 "age": 30  
    cbor_encode_text_stringz(&map_encoder, "age");  
    cbor_encode_uint(&map_encoder, 30);  
  
    // 结束映射  
    cbor_encoder_close_container(&encoder, &map_encoder);
  
    // 获取实际使用的缓冲区大小和CBOR数据  
    size_t encoded_size = cbor_encoder_get_buffer_size(&encoder, cbor_buffer);  
  
    // 打印或处理CBOR数据  
    printf("Encoded CBOR data (size: %zu):\n", encoded_size);  
    for (size_t i = 0; i < encoded_size; i++) {  
        printf("%02X ", cbor_buffer[i]);  
    }  
    printf("\n");

    // 初始化解析器  
    CborParser parser;  
    CborValue it;  
    CborError err = cbor_parser_init(cbor_buffer, encoded_size, 0, &parser, &it);  
    if (err != CborNoError) {  
        fprintf(stderr, "Failed to initialize parser\n");  
        return 1;  
    }

    dumprecursive(&it, 0);
  
    return 0;  
}

示例程序二

// 创建array数据
int test3()
{  
    // 分配足够的内存来存储CBOR编码的数据  
    // 注意:这个大小是估计的,实际大小可能更小或更大  
    uint8_t cbor_buffer[256];  
    size_t buffer_size = sizeof(cbor_buffer);  
  
    // 初始化编码器  
    CborEncoder encoder;  
    cbor_encoder_init(&encoder, cbor_buffer, buffer_size, 0);  
  
    // 开始一个数组  
    CborEncoder array_encoder;  
    cbor_encoder_create_array(&encoder, &array_encoder, CborIndefiniteLength);  
  
    // 向数组中添加整数  
    cbor_encode_uint(&array_encoder, 1);  
    cbor_encode_uint(&array_encoder, 2);  
    cbor_encode_uint(&array_encoder, 3);  
  
    // 结束数组  
    cbor_encoder_close_container(&encoder, &array_encoder);  
  
    // 获取实际使用的缓冲区大小和CBOR数据  
    size_t encoded_size = cbor_encoder_get_buffer_size(&encoder, cbor_buffer);  
  
    // 打印或处理CBOR数据  
    printf("Encoded CBOR array data (size: %zu):\n", encoded_size);  
    for (size_t i = 0; i < encoded_size; i++) {  
        printf("%02X ", cbor_buffer[i]);  
    }  
    printf("\n");

    // 初始化解析器  
    CborParser parser;  
    CborValue it;  
    CborError err = cbor_parser_init(cbor_buffer, encoded_size, 0, &parser, &it);  
    if (err != CborNoError) {  
        fprintf(stderr, "Failed to initialize parser\n");  
        return 1;  
    }

    dumprecursive(&it, 0);
  
    return 0;  
}

示例三

// 创建一个array,并在里面添加map、字符串、byte等
int test4() 
{  
    // 分配足够的内存来存储CBOR编码的数据  
    uint8_t cbor_buffer[256];  
    size_t buffer_size = sizeof(cbor_buffer);  
  
    // 初始化编码器  
    CborEncoder encoder;  
    cbor_encoder_init(&encoder, cbor_buffer, buffer_size, 0);  
  
    // 开始一个数组  
    CborEncoder array_encoder;  
    cbor_encoder_create_array(&encoder, &array_encoder, CborIndefiniteLength);  
  
    // 添加一个映射到数组中  
    CborEncoder map_encoder;  
    cbor_encoder_create_map(&array_encoder, &map_encoder, CborIndefiniteLength);  
  
    // 在映射中添加键值对  
    cbor_encode_text_stringz(&map_encoder, "name");  
    cbor_encode_text_stringz(&map_encoder, "John");  
  
    cbor_encode_text_stringz(&map_encoder, "age");  
    cbor_encode_uint(&map_encoder, 30);  
  
    // 结束映射  
    cbor_encoder_close_container(&array_encoder, &map_encoder);  
  
    // 添加一个字符串到数组中  
    cbor_encode_text_stringz(&array_encoder, "Hello, CBOR!");  
  
    // 添加byte
    uint8_t bytes[] = {0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09};
    cbor_encode_byte_string(&array_encoder, bytes, sizeof(bytes));

    // 结束数组  
    cbor_encoder_close_container(&encoder, &array_encoder);  
  
    // 获取实际使用的缓冲区大小和CBOR数据  
    size_t encoded_size = cbor_encoder_get_buffer_size(&encoder, cbor_buffer);  
  
    // 打印或处理CBOR数据  
    printf("Encoded CBOR array data (size: %zu):\n", encoded_size);  
    for (size_t i = 0; i < encoded_size; i++) {  
        printf("%02X ", cbor_buffer[i]);  
    }  
    printf("\n");

     // 初始化解析器  
    CborParser parser;  
    CborValue it;  
    CborError err = cbor_parser_init(cbor_buffer, encoded_size, 0, &parser, &it);  
    if (err != CborNoError) {  
        fprintf(stderr, "Failed to initialize parser\n");  
        return 1;  
    }

    dumprecursive(&it, 0);  
  
    return 0;
}

实例中使用到的其他函数

static void indent(int nestingLevel)
{
    while (nestingLevel--)
        printf("  ");
}

static void dumpbytes(const uint8_t *buf, size_t len)
{
    while (len--)
        printf("%02X", *buf++);
    printf("\n");
}

static CborError dumprecursive(CborValue *it, int nestingLevel)
{
    while (!cbor_value_at_end(it)) {
        CborError err;
        CborType type = cbor_value_get_type(it);

        indent(nestingLevel);
        switch (type) {
        case CborArrayType:
        case CborMapType: {
            // recursive type
            CborValue recursed;
            assert(cbor_value_is_container(it));
            puts(type == CborArrayType ? "Array[" : "Map[");
            err = cbor_value_enter_container(it, &recursed);
            if (err)
                return err;       // parse error
            err = dumprecursive(&recursed, nestingLevel + 1);
            if (err)
                return err;       // parse error
            err = cbor_value_leave_container(it, &recursed);
            if (err)
                return err;       // parse error
            indent(nestingLevel);
            puts("]");
            continue;
        }

        case CborIntegerType: {
            int64_t val;
            cbor_value_get_int64(it, &val);     // can't fail
            printf("%lld\n", (long long)val);
            break;
        }

        case CborByteStringType: {
            uint8_t *buf;
            size_t n;
            err = cbor_value_dup_byte_string(it, &buf, &n, it);
            if (err)
                return err;     // parse error
            dumpbytes(buf, n);
            puts("");
            free(buf);
            continue;
        }

        case CborTextStringType: {
            char *buf;
            size_t n;
            err = cbor_value_dup_text_string(it, &buf, &n, it);
            if (err)
                return err;     // parse error
            printf("\"%s\"\n", buf);
            free(buf);
            continue;
        }

        case CborTagType: {
            CborTag tag;
            cbor_value_get_tag(it, &tag);       // can't fail
            printf("Tag(%lld)\n", (long long)tag);
            break;
        }

        case CborSimpleType: {
            uint8_t type;
            cbor_value_get_simple_type(it, &type);  // can't fail
            printf("simple(%u)\n", type);
            break;
        }

        case CborNullType:
            puts("null");
            break;

        case CborUndefinedType:
            puts("undefined");
            break;

        case CborBooleanType: {
            bool val;
            cbor_value_get_boolean(it, &val);       // can't fail
            puts(val ? "true" : "false");
            break;
        }

        case CborDoubleType: {
            double val;
            if (false) {
                float f;
        case CborFloatType:
                cbor_value_get_float(it, &f);
                val = f;
            } else {
                cbor_value_get_double(it, &val);
            }
            printf("%g\n", val);
            break;
        }
        case CborHalfFloatType: {
            uint16_t val;
            cbor_value_get_half_float(it, &val);
            printf("__f16(%04x)\n", val);
            break;
        }

        case CborInvalidType:
            // assert(false);      // can't happen
            printf("CborInvalidType");
            break;
        }

        err = cbor_value_advance(it);
        if (err)
            return err;
    }
    return CborNoError;
}
  • 5
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值