Кодирование и декодирование uint8_t с использованием библиотеки TinyCbor C

Я реализую приложение на 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, Или если установлено значение 21 тогда он возвращает мне тип как CborBooleanType или же CborNullType,

  1. Что не так с кодом

  2. Как кодировать и декодировать uint8_t используя TinyCbor.

0 ответов

У вас здесь происходит несколько вещей.

cbor_encoder_create_array(& кодировать, & массив, CborIndefiniteLength);

Не используйте неопределенную длину, если не планируете транслировать кодировку. Если при кодировании перед вами все данные, используйте определенную длину. Посмотрите, почему здесь: Сериализуйте карту фиксированного размера в CBOR, и я не уверен, какую версию вы используете, но объекты неопределенной длины были, по крайней мере, довольно недавно элементом списка TO DO для TinyCBOR.

cbor_value_get_simple_type(& массив, &val);

Здесь вам не нужно ничего простого. Простые типы - это примитивы, которые в большинстве своем не определены. Тип CBOR по умолчанию - int64_t, signed long long. Simple допускает естественную остановку на 8 битах, но 20 in simple является логическим ложным. 21 верно, 22 ноль. Вы это уже обнаружили. Он не может хранить отрицательные числа или числа с плавающей запятой, и хотя вы могли бы использовать его для представления 8-битного числа, такого как "100", вам этого не следует. Хорошие новости о типах CBOR заключаются в том, что, хотя по умолчанию используется 64-битная версия, для кодирования используется минимум памяти. Таким образом, сохранение 100 в CBOR - это один байт, а не 8, не считая служебных данных за секунду.

Под накладными расходами я имею в виду, когда вы кодируете целое число cbor, первые три бита означают БЕЗ ПОДПИСАННОГО ЦЕЛОГО (двоичный 000), один бит зарезервирован, остальные 4 бита являются значением, поэтому, если у вас было небольшое значение, которое соответствовало этим четырем битам (значение 0-23) вы можете получить все это одним байтом. Этот зарезервированный бит странный, см. Диаграмму здесь, чтобы понять это: https://en.m.wikipedia.org/wiki/CBOR Итак, 24-255 требует кодирования 2 байта и т.д. и т.д. потому что может.

Вкратце, CBOR не будет использовать больше места, чем необходимо - НО - это не строго типизированный сериализатор! Если вы имеете в виду, что в этом массиве хранится 100 внутри 8 бит, а кто-то хранит 10000 для 16 бит, он будет выглядеть / работать нормально, пока вы не перейдете к синтаксическому анализу и не сохраните большое число в 8-битном месте. Вам необходимо преобразовать или проверить свои данные. Я рекомендую разобрать ЗАТЕМ проверять.

cbor_value_get_simple_type(& массив, &fval);

cout << "значение с плавающей запятой: " << fval << endl;

Мне пришлось бы посмотреть код TinyCBOR, но я думаю, что это счастливый случай и технически не поддерживается для работы. Поскольку простые типы используют те же три основных бита, вы можете получить 64-битную точность значения с помощью get_simple. Вместо этого вам следует проверить тип и сделать правильный вызов для получения float полной или половинной точности.

TinyCBOR довольно хорош, но определенно есть пара ошибок. Это действительно помогает понять кодировку CBOR, даже если вы доверяете сериализатору работу за вас.

Использование CborError cbor_encode_uint(CborEncoder *encoder, uint64_t value) вместо. Эта функция будет кодировать целочисленное значение без знака с наименьшим представлением.

Другие вопросы по тегам