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

Я реализую приложение на основе 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.


person User7723337    schedule 08.06.2018    source источник
comment
Я только что просмотрел github (из любопытства). Я считаю, что вы используете неправильную функцию для своего намерения. Если я правильно понял, cbor_encode_simple_value() кодирует что-то вроде идентификации типа. Следовательно, принимаются значения только для зарегистрированных типов (а их, кажется, всего 20 или 21). append_to_buffer() или cbor_encode_uint() кажется лучшим выбором. (Обратите внимание, что я никогда раньше не слышал о TinyCbor.)   -  person Scheff's Cat    schedule 08.06.2018


Ответы (2)


У вас тут кое-что происходит.

cbor_encoder_create_array(&encode, &array, CborIndefiniteLength);

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

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

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

Под накладными расходами я имею в виду, когда вы кодируете целое число 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(&массив, &fval);

cout ‹‹ плавающее значение: ‹‹ fval ‹‹ endl;

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

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

person mint branch conditioner    schedule 20.11.2019

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

person Daniel    schedule 14.03.2019