Зерновые сериализуют CString Vector - PullRequest
0 голосов
/ 02 июня 2018

РЕДАКТИРОВАТЬ: // Получил работу благодаря ответу ниже, добавив код, который в настоящее время работает и тестовый случай на случай, если кто-то может найти это полезным.

// Add as another type for Cereal or inside string.hpp in Cereal includes      
  template<class Archive> inline
      void CEREAL_SAVE_FUNCTION_NAME(Archive & ar, CString str)
  {
      // Save number of chars + the data
      size_type size = (str.GetLength() + 1) * sizeof(TCHAR);
      ar(size);
      ar(binary_data(str.GetBuffer(), static_cast<std::size_t>(size)));
      str.ReleaseBuffer();
  }

  template<class Archive> inline
      void CEREAL_LOAD_FUNCTION_NAME(Archive & ar, CString & str)
  {
      size_type size;
      ar(size);
      ar(binary_data(str.GetBuffer(static_cast<std::size_t>(size)), static_cast<std::size_t>(size)));
      str.ReleaseBuffer();
  }

Ниже приведен код Iиспользуется для проверки, он правильно выводит все элементы вектора.

class Stuff
{
public:
    Stuff() {}
    std::vector<CString> vec;
private:
    friend class cereal::access;
    template <class Archive>
    void serialize(Archive & ar)
    {
        ar(vec);
    }
};

int main()
{
    Stuff myStuff, otherStuff;

    myStuff.vec.push_back(L"Testing different length CStrings");
    myStuff.vec.push_back(L"Separator");
    myStuff.vec.push_back(L"Is it working yet??");
    myStuff.vec.push_back(L"1234567890");
    myStuff.vec.push_back(L"TestingTestingTestingtestingTesting");

    {
    std::ofstream file("out.txt", std::ios::binary);
    cereal::BinaryOutputArchive output(file);
    output(myStuff);
    }

    {
        std::ifstream file("out.txt", std::ios::binary);
        cereal::BinaryInputArchive input(file);
        input(otherStuff);
    }

    int nSize = otherStuff.vec.size();

    for (int x = 0; x < nSize; x++)
    {
        std::wcout << (LPCWSTR)otherStuff.vec[x] << std::endl;
    }
    return 0;
}

Спасибо Barmak Shemirani за помощь.

1 Ответ

0 голосов
/ 02 июня 2018

Если ваш класс сериализации знает, как обрабатывать std::vector<std::string> (вы должны протестировать его со строками разных размеров), он также может знать, как обрабатывать CString (версия с широким типом символов), рассматривая его как двоичные данные, предполагая, что файлоткрывается в двоичном формате.

Эти флаги необходимы для открытия в двоичном режиме в Windows:

std::ofstream file("out.txt", std::ios::binary);
std::ifstream file("out.txt", std::ios::binary);

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

В качестве альтернативы, вы можете конвертировать CString (UTF16) в UTF8

std::vector<std::string> vec;
vec.push_back((const char*)CW2A(L"abc-unicode-ελληνική", CP_UTF8));

Вам придется конвертировать обратно в CString, как только вы прочитаете его из архива:

CString s = CA2W(vec[0].c_str(), CP_UTF8);


В двоичном формате используйте правильный размер для сохранения CString.Что-то вроде:
CEREAL_SAVE_FUNCTION_NAME...
size_type size = (str.GetLength() + 1) * sizeof(TCHAR);
ar(size);
ar(binary_data(str.GetBuffer(), size));
str.ReleaseBuffer();

При чтении в CString, убедитесь, что буфер достаточно большой, вызвав str.GetBuffer(size) вместо str.GetBuffer() Код должен выглядеть примерно так:

CEREAL_LOAD_FUNCTION_NAME...
size_type size;
ar(size);
ar(binary_data(str.GetBuffer(size), size);
str.ReleaseBuffer();

Чтобы сериализовать векторы, сохраните размер вектора, затем сохраните каждый элемент вектора.Чтобы прочитать векторное измерение, а затем прочитать, что много элементов из архива.Если ваш класс сериализации не имеет автоматизации для этого.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...