Увеличенный двоичный архив сериализации, дающий неверный вывод

Я пытаюсь сериализировать класс.

Определение класса:

class StartPeerSessionRequest {
public:
StartPeerSessionRequest();
virtual ~StartPeerSessionRequest();
void composeRequestwithHardCodeValues();
void save();
stringstream serializedRequest;
/*boost::serialization::binary_object serlreq;*/

private:
StartPeerSessionRequest(const StartPeerSessionRequest &);

uint16_t mProtocolVersion;
uint16_t mSessionFlags;
uint16_t mMaxResponseLength;
string   mMake;
string   mModel;
string   mSerialNumber;
uint8_t  mTrackDelay;
string   mHeadUnitModel;
string   mCarModelYear;
string   mVin;
uint16_t mVehicleMileage;
uint8_t  mShoutFormat;
uint8_t  mNotificationInterval;

friend class boost::serialization::access;
template <typename Archive> void serialize(Archive &ar, const unsigned int version);
};

StartPeerSessionRequest::StartPeerSessionRequest() {

mProtocolVersion      = 1 * 10000 + 14 * 100 + 4;
mSessionFlags         = 1;
mMaxResponseLength    = 0;
mMake                 = "MyMake";
mModel                = "MyModel";
mSerialNumber         = "10000";
mTrackDelay           = 0;
mHeadUnitModel        = "Headunit";
mCarModelYear         = "2014";
mVin                  = "1234567980";
mVehicleMileage       = 1000;
mShoutFormat          = 3;
mNotificationInterval = 1;
}

template <class Archive> void StartPeerSessionRequest::serialize(Archive &ar, const unsigned int version) {
ar & mProtocolVersion;
ar & mSessionFlags;
ar & mMaxResponseLength;
ar & mMake;
ar & mModel;
ar & mSerialNumber;
ar & mTrackDelay;
ar & mHeadUnitModel;
ar & mCarModelYear;
ar & mVin;
ar & mVehicleMileage;
ar & mShoutFormat;
ar & mNotificationInterval;
}

void StartPeerSessionRequest::save() {
boost::archive::binary_oarchive oa(serlreq, boost::archive::no_header);
oa << (*this);
/*cout<<"\n binary_oarchive :"<<serlreq.size();*/

boost::archive::text_oarchive ota(serializedRequest, boost::archive::no_header);
ota << (*this);
cout << "\n text_oarchive :" << serializedRequest.str() << "size :" << serializedRequest.str().size();
}

serializedRequest.str.size() дает мне длину 87

На самом деле это должно дать мне 65 байтов. (Я посчитал, что вы можете понять это из конструктора)

Я подозреваю, что это добавление длины между ними.

Я пытался использовать text_archive также это не работает.

Мне нужно просто сериализовать членов класса как есть.

Я думаю, мне нужно использовать некоторые черты или обертки.

пожалуйста, дайте мне знать

Спасибо

2

Решение

Итак, просто чтобы посмотреть, как я это сделаю, я попытался достичь оптимальных размеров, которые я рассчитал на обороте моей салфетки:

Я могу видеть, как вы ожидаете 57, 63 или 75 байтов

mProtocolVersion      = 1*10000+14*100+4; // 2 bytes
mSessionFlags         = 1;                // 2 bytes
mMaxResponseLength    = 0;                // 2 bytes
mMake                 = "MyMake";         // 6 bytes + length
mModel                = "MyModel";        // 7 bytes + length
mSerialNumber         = "10000";          // 5 bytes + length
mTrackDelay           = 0;                // 1 byte
mHeadUnitModel        = "Headunit";       // 8 bytes + length
mCarModelYear         = "2014";           // 4 bytes + length
mVin                  = "1234567980";     // 10 bytes + length
mVehicleMileage       = 1000;             // 2 byte
mShoutFormat          = 3;                // 1 byte
mNotificationInterval = 1;                // 1 byte
// -------------------------------------- // 51 bytes + 6 x length

В этом случае я создал двоичный код сериализации, используя Boost Spirit (Karma для сериализации и Qi для десериализации). Я сделал размер настраиваемого поля длины (8,16,32 или 64-битный без знака).

Вот рабочее доказательство концепции: Жить на Колиру

generate()

Функция-член const generate делегирует работу вспомогательным функциям в отдельном пространстве имен:

template <typename Container>
bool generate(Container& bytes) const {
auto out = std::back_inserter(bytes);

using my_serialization_helpers::do_generate;
return do_generate(out, mProtocolVersion)
&& do_generate(out, mSessionFlags)
&& do_generate(out, mMaxResponseLength)
&& do_generate(out, mMake)
&& do_generate(out, mModel)
&& do_generate(out, mSerialNumber)
&& do_generate(out, mTrackDelay)
&& do_generate(out, mHeadUnitModel)
&& do_generate(out, mCarModelYear)
&& do_generate(out, mVin)
&& do_generate(out, mVehicleMileage)
&& do_generate(out, mShoutFormat)
&& do_generate(out, mNotificationInterval);
}

Обратите внимание, что

  • do_generate перегрузки могут быть свободно добавлены по мере необходимости для будущих типов
  • контейнер может быть легко переключен, например, с std::vector<unsigned char>Например, boost::interprocess::containers::string<char, char_traits<char>, boost::interprocess::allocator<char, boost::interprocess::managed_shared_memory::segment_manager> >,

parse()

Метод разбора очень похож, за исключением того, что делегирует do_parse перегрузки, чтобы сделать работу.

тестирование

Программа испытаний туда-обратно со всеми возможными конфигурациями:

  • 8-битное поле длины, нетто 57 байт, с ускоренной сериализацией: 70
  • 16-битное поле длины, нетто 63 байта, с ускоренной сериализацией: 76
  • 32-битное поле длины, нетто 75 байт, с форсированной сериализацией: 88
  • Поле длиной 64 бита, нетто 99 байт, с ускоренной сериализацией: 112

Как вы можете видеть, это даже не тот Возмутительно, что естественное решение Boost Serialization займет 107 байтов в моей системе (это всего на 8 байт больше, чем в моей последней конфигурации).

Отметим также, что, поскольку все генераторы Кармы используют любой выходной итератор, подключить его непосредственно в Низкоуровневые Операции Boost Archive для производительности и чтобы избежать выделения промежуточного хранилища.

1

Другие решения

Похоже, у вас есть очень специфические предположения о том, как Boost Serialization следует сериализовать в свой собственный непереносимый двоичный формат.

Ускоренная сериализация намного более высокого уровня, более или менее специально разработана для работы с данными, не относящимися к POD. Если вы настаиваете, вы сможете напрямую сериализовать массив вашего типа POD. В вашем вопросе, однако, класс совсем не POD и, следовательно, в любом случае не побитально сериализуемый.

Для переносных архивов см. EOS Portable Archive.

В Boost Archives есть дополнительные флаги, которые подавляют заголовок формата:

enum archive_flags {
no_header = 1,          // suppress archive header info
no_codecvt = 2,         // suppress alteration of codecvt facet
no_xml_tag_checking = 4 // suppress checking of xml tags - igored on saving
};

Увидеть Архив моделей

Вот справочная информация, чтобы увидеть, что вводит издержки по сравнению с простой побитовой сериализацией:

0