2 Kasım 2017 Perşembe

serialization STL Desteği

Giriş
Boost bazı STL sınıfları için serialization desteği veriyor. Tek yapmamız gereken, bazı dosyaları include etmek. boost serialization ile kaydedilen stl collection sınıflarında ilk önce collection'ın boyutu yazılıyor.

std::bitset
Şu satırı dahil ederiz.
#include <boost/serialization/bitset.hpp>
std::complex
Şu satırı dahil ederiz.
#include <boost/serialization/complex.hpp>
std::dequeue
Şu satırı dahil ederiz.
#include <boost/serialization/deque.hpp>
std::list
Şu satırı dahil ederiz.
#include <boost/serialization/list.hpp>
std::map
Şu satırı dahil ederiz.
#include <boost/serialization/map.hpp>
Örnek
Elimizde şöyle bir kod olsun. Bu kod verilen her tipi kaydedip okuyabilir.
template <typename SaveClass>
void saveData(const std::string filename, SaveClass const& c)
{
  std::remove(filename.c_str());
  std::ofstream ofs(filename);
  boost::archive::text_oarchive ta(ofs);

  ta << c;
}

template <typename LoadClass>
void loadData(const std::string filename, LoadClass& c)
{
  std::ifstream ifs(filename);
  boost::archive::text_iarchive ta(ifs);
  ta >> c;
}
Çağırmak için şöyle yaparız.
std::string filename = "userandPassBackup.txt";
{
  std::map<std::string, std::string> userandPass {
    { "John", "pa$$w0rd" },
    { "Jane", "welcome01" } };
    saveData(filename, userandPass);
  
}
{
  std::map<std::string, std::string> userandPass;
  loadData(filename, userandPass);

}
Örnek
Elimizde şöyle bir map olsun.
typedef   map<int,std::string> groups;
groups  e_group;
Bu nesneyi xml olarak serialize edelim.
template<class archive>
void serialize(archive& ar, const unsigned int version)
{
  using boost::serialization::make_nvp;
  ar & make_nvp("Connections", e_group);
}
Çıktı olarak şunu alırız. map'in içindeki değerler first ve second tag'leri olarak kaydedilir.
<?xml version="1.0" encoding="UTF-8" standalone="yes" ?>
<!DOCTYPE boost_serialization>
<boost_serialization signature="serialization::archive" version="14">
<Connections class_id="0" tracking_level="0" version="0">
  <Connections class_id="1" tracking_level="0" version="0">
    <count>2</count>
    <item_version>0</item_version>
      <item class_id="2" tracking_level="0" version="0">
        <first>1</first>
        <second>ETOTO</second>
      </item>
      <item>
        <first>2</first>
        <second>ETOTO</second>
      </item>
    </Connections>
</Connections>
</boost_serialization>
Bunu değiştirmek için şöyle yaparız.
namespace boost {
  namespace serialization { 
    template <typename Ar>
    void serialize(Ar& ar, std::pair<int const, std::string>& p, unsigned) {
      ar & make_nvp("groupid", p.first) & make_nvp("groupType", p.second);
    }
  }
}
Çıktı olarak şunu alırız.
<Connections class_id="1" tracking_level="0" version="0">
  <count>2</count>
  <item_version>0</item_version>
  <item class_id="2" tracking_level="0" version="0">
    <groupid>1</groupid>
    <groupType>ETOTO</groupType>
  </item>
  <item>
    <groupid>2</groupid>
    <groupType>ETOTO</groupType>
  </item>
</Connections>
std::pair
Örnek
Elimizde std::pair içeren bir vector olsun
template <class TKey, class TValue>
class DataModel
{
public:
  DataModel() = default;
  ~DataModel() = default;

private:
  std::vector<boost::shared_ptr<std::pair<TKey, TValue>>> mData = {};
}
Şöyle yaparız
friend class boost::serialization::access;
template <typename Archive>
void serialize( Archive &ar, const unsigned int version )
{
  ar &boost::serialization::make_nvp( "Data", mData );
}

std::shared_ptr
Şu satırı dahil ederiz.
#include <boost/serialization/shared_ptr.hpp>
Açıklaması şöyle
Depending on how the class is used and other factors, serialized objects may be tracked by memory address. This prevents the same object from being written to or read from an archive multiple times. These stored addresses can also be used to delete objects created during a loading process that has been interrupted by throwing of an exception.
Bir sürü shared_ptr nesnesi göndermek için bunları bir vector'e doldurup sonra göndermek daha iyi. Yazan tarafta şöyle yaparız.
std::vector<std::shared_ptr<Message>> messages;
for (int i = 0; i < 10; i++) {
  std::shared_ptr<Message> dl = std::make_shared<Message>();
  ...
  messages.emplace_back(dl);
}

boost::archive::text_oarchive archive(stream);
archive << messages;
Okuyan tarafta şöyle yaparız.
while (true) {
  try {
    std::vector<std::shared_ptr<Message>> messages;
    archive >> messages;
    ...
  } catch (std::exception &ex) {
    cout << ex.what() << endl;
    ...
}
std::string
Şu satırı dahil ederiz.
#include <boost/serialization/string.hpp>
std::unordered_map
Şu satırı dahil ederiz.
#include <boost/serialization/unordered_map.hpp>
Şöyle yaparız.
class foo {
  std::unordered_map<int, int> m_map;
public:
  friend class boost::serialization::access;
  template<class Archive>
  void serialize(Archive & ar, const unsigned int) {
    ar & m_map;
  }
};
std::unique_ptr
Şu satırı dahil ederiz.
#include <boost/serialization/unique_ptr.hpp>
Örnek
Elimizde şöyle bir kod olsun. Parent ve Child sınıfları çift yönlü ilişkiye sahip olsun
class Parent;

class Child {
public:
  Child(Parent *parent) :
    m_parent(parent)  {}

  Parent *m_parent          { nullptr };
  
private:
  friend class boost::serialization::access;
  template <class Archive> void serialize(Archive &ar, unsigned) {
    ar & m_parent; 
  }

  Child() = default;
};

class Parent {
public:
  Parent() : m_child(std::make_unique<Child>(this)) {}


  friend class boost::serialization::access;
  template <class Archive> void serialize(Archive &ar, unsigned) {
    ar & m_child; 
  }

  std::unique_ptr<Child> m_child;
};
Yazıp okuman için şöyle yaparız
std::stringstream ss;
{
  boost::archive::text_oarchive oa(ss);

  Parent p;
  assert(&p == p.m_child->m_parent);
  oa << p;
}

std::cout << ss.str();

{
  boost::archive::text_iarchive ia(ss);

  Parent p;
  // let's purposelly break the invariants so we know deserialization
  // does restore them as required, and we not just "getting lucky":
  p.m_child->m_parent = nullptr;
  
  assert(&p != p.m_child->m_parent);
  
  p.m_child.reset();

  // now deserialize
  ia >> p;

  assert(&p == p.m_child->m_parent);
  
}
std::vector
Şu satırı dahil ederiz.
#include <boost/serialization/vector.hpp>


Hiç yorum yok:

Yorum Gönder