MessagePack C API

Рассматривая C API для MessagePack, существует ряд функций для соответствующей сериализации (упаковки) данных в соответствии с типом: msgpack_pack_uint8, msgpack_pack_int32...

Похоже, в API нет аналогичного вызова для распаковки данных. msgpack_unpack_next возвращает msgpack_object, Эти объекты имеют только грубую гранулярность типов (самый большой из типов: int64, double, ...), основываясь на включенных перечислениях.

Я что-то здесь упускаю? Является ли ожидание, что грубый объект будет использован, а затем приведен?

Как правильно распаковывать вещи?

Кроме того, есть ли хорошая документация или примеры использования? Те, что на сайте, тривиальны.

1 ответ

Решение

Во время распаковки любое целочисленное значение всегда сохраняется в msgpack_object как 64-разрядное целое число фиксированной ширины (int64_t если отрицательный, uint64_t иначе).

Увидеть cpp/src/msgpack/object.h для более подробной информации о msgpack_object и др., и cpp/src/msgpack/unpack.c чтобы увидеть, как msgpack обрабатывает логику распаковки, например:

static inline int template_callback_int8(unpack_user* u,
                                         int8_t d,
                                         msgpack_object* o) {
    if(d >= 0) {
        o->type = MSGPACK_OBJECT_POSITIVE_INTEGER; o->via.u64 = d;
        return 0;
    }
    else {
        o->type = MSGPACK_OBJECT_NEGATIVE_INTEGER; o->via.i64 = d;
        return 0;
    }
}

Это связано с тем, что во время упаковки msgpack динамически выбирает наиболее оптимальный способ кодирования целого числа в соответствии с его значением, например, если вы используете msgpack_pack_uint16 чтобы упаковать ваше целое число:

  • оно будет сохранено в 1 байте, если значение находится в [0, 127],
  • 2 байта с 0xcc в качестве первого байта, если значение находится в [128, 255],
  • 3 байта с 0xcd как первый байт в противном случае.

Увидеть msgpack_pack_real_uint16 от cpp/src/msgpack/pack_template.h Больше подробностей.


Другими словами, во время распаковки msgpack использует достаточно большой положительный или отрицательный результат (проверьте, obj.type является MSGPACK_OBJECT_POSITIVE_INTEGER или же MSGPACK_OBJECT_NEGATIVE_INTEGER) для хранения любого целочисленного значения. Так что вам решать:

  • приведение, если вы всегда можете предположить, что значения никогда не будут превышать ваш тип приведение,
  • или, динамически (с маской) проверить, является ли значение недостаточно большим для вашего типа получателя,
  • или всегда используйте int64_t или же uint64_t,

Наконец, тестовый набор C (msgpack/cpp/test/msgpackc_test.cpp) может быть полезно просмотреть примеры кода.

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