icu ::UnicodeString с сериализацией boost

#c #serialization #boost #icu

#c #сериализация #повышение #icu

Вопрос:

Я пытаюсь сериализовать icu ::UnicodeString с помощью библиотеки сериализации boost, но у меня возникли проблемы.

Icu::UnicodeString не имеет требуемой функции serialize для ее сериализации. Итак, я попытался создать его, но я не уверен, как это сделать. Пример кода:

 #include <map>
#include <sstream>
#include <fstream>
#include <unicode/unistr.h>
#include <unicode/ustream.h>

#include <boost/serialization/map.hpp>
#include <boost/archive/text_iarchive.hpp>
#include <boost/archive/text_oarchive.hpp>

namespace boost {
namespace serialization {

template<class Archive>
inline void save(
    Archive amp; ar,
    const icu_55::UnicodeStringamp; str,
    const unsigned int /* file_version */
){
}

template<class Archive>
inline void load(
    Archive amp; ar,
    icu_55::UnicodeStringamp; str,
    const unsigned int /* file_version */
){
}

// split non-intrusive serialization function member into separate
// non intrusive save/load member functions
template<class Archive>
inline void serialize(
    Archive amp; ar,
    icu_55::UnicodeStringamp; str,
    const unsigned int file_version
){
    boost::serialization::split_free(ar, str, file_version);
}

} // serialization
} // namespace boost

int main()
{

   std::map<icu::UnicodeString, int> map = {{"asssdasd",2}, {"qwe",1}, {"Zxc",55}};
   std::stringstream ss;
   boost::archive::text_oarchive oarch(ss);
   oarch << map;
   std::map<icu::UnicodeString, int> new_map;
   boost::archive::text_iarchive iarch(ss);
   iarch >> new_map;

   std::cout << (map == new_map) << std::endl;
}
  

Скомпилируйте что-то вроде g -o new new.cpp -std=c 11 -lboost_serialization -licuuc

В настоящее время функции «сохранить» и «загрузить» не реализованы. Я попытался выполнить только те ar amp; str; инструкции, которые используются в руководствах boost, но у меня возникла ошибка сегментации, которую я также не могу исправить.

Ответ №1:

Я никогда не работал с LibICU напрямую, поэтому, вероятно, кто-то может просмотреть этот код.

Однако, исходя из моего опыта использования сериализации Boost, я думаю, что это должно быть полезно:

 template <class Archive>
inline void save(Archive amp;ar, icu_55::UnicodeString const amp;str, const unsigned int) {
    auto sz = str.getCapacity();
    auto len = str.length();
    auto buf = str.getBuffer();

    if (!buf) throw std::invalid_argument("str");

    ar amp; sz amp; len amp; boost::serialization::make_array(buf, sz);
}

template <class Archive>
inline void load(Archive amp;ar, icu_55::UnicodeString amp;str, const unsigned int)
{
    size_t sz, len;
    ar amp; sz amp; len;
    auto buf = str.getBuffer(sz);
    if (!buf) throw std::invalid_argument("str");

    try {
        ar amp; boost::serialization::make_array(buf, sz);
    } 
    catch(...) {
        str.releaseBuffer(len);
        throw;
    }
    str.releaseBuffer(len);
}
  

Это работает для простого предоставленного тестового примера:

 #include <fstream>
#include <map>
#include <sstream>
#include <iostream>
#include <unicode/unistr.h>
#include <unicode/ustream.h>

#include <boost/archive/text_iarchive.hpp>
#include <boost/archive/text_oarchive.hpp>
#include <boost/serialization/map.hpp>

namespace boost { namespace serialization {

    template <class Archive>
    inline void save(Archive amp;ar, icu_55::UnicodeString const amp;str, const unsigned int) {
        auto sz = str.getCapacity();
        auto len = str.length();
        auto buf = str.getBuffer();

        if (!buf) throw std::invalid_argument("str");

        ar amp; sz amp; len amp; boost::serialization::make_array(buf, sz);
    }

    template <class Archive>
    inline void load(Archive amp;ar, icu_55::UnicodeString amp;str, const unsigned int)
    {
        size_t sz, len;
        ar amp; sz amp; len;
        auto buf = str.getBuffer(sz);
        if (!buf) throw std::invalid_argument("str");

        try {
            ar amp; boost::serialization::make_array(buf, sz);
        } 
        catch(...) {
            str.releaseBuffer(len);
            throw;
        }
        str.releaseBuffer(len);
    }


    // split non-intrusive serialization function member into separate
    // non intrusive save/load member functions
    template <class Archive>
    inline void serialize(Archive amp;ar, icu_55::UnicodeString amp;str, const unsigned int file_version) {
        boost::serialization::split_free(ar, str, file_version);
    }

} } // serialization // namespace boost

int main() {
    std::map<icu::UnicodeString, int> const map = { { "asssdasd", 2 }, { "qwe", 1 }, { "Zxc", 55 } };
    std::stringstream ss;
    {
        boost::archive::text_oarchive oarch(ss);
        oarch << map;
    }

    {
        std::map<icu::UnicodeString, int> new_map;
        boost::archive::text_iarchive iarch(ss);
        iarch >> new_map;

        std::cout << (map == new_map) << std::endl;
    }
}
  

С принтами

 1
  

Комментарии:

1. Неплохо. Работает! Спасибо!

2. Вы действительно не должны брать случайные фрагменты кода от неспециалистов в Интернете без тщательного изучения. Я только что добавил еще немного безопасности для обработки ошибок / исключений. Возможно, вы можете поместить код в Code Review для проверки любым гуру ICU?