C++ Cereal

Da Andreabont's Wiki.

Cereal è una libreria header-only in grado di fornire funzionalità di serializzazione e deserializzazione di strutture dati del C++ in format JSON, XML e binario.

Compilare la libreria

La compilazione è neessaria solo allo scopo di eseguire gli unit test forniti.

Dipendenze

sudo zypper install gcc-32bit libstdc++48-devel-32bit

Sorgente

E' possibile trovare il sorgente versionato su git, compilabile attraverso cmake.

git clone https://github.com/USCiLab/cereal.git
mkdir -p cereal/build
cd cereal/build
cmake ..
make
make test

Formato di serializzazione

E' possibile scegliere il formato da usare nella serializzazione includendo il corretto file di header e chiamando la classe corretta.

Formato File da includere Classe da chiamare
JSON cereal/archives/json.hpp cereal::JSONInputArchive oppure cereal::JSONOutputArchive
XML cereal/archives/xml.hpp cereal::XMLInputArchive oppure cereal::XMLOutputArchive
Binario cereal/archives/binary.hpp cereal::BinaryInputArchive oppure cereal::BinaryOutputArchive
Binario portabile cereal/archives/portable_binary.hpp cereal::PortableBinaryInputArchive oppure cereal::PortableBinaryOutputArchive

Utilizzo della libreria

Per utilizzare la libreria è necessario semplicemente includere i corretti file di header.

Selezione uscita

In base a cosa selezione di uscita posso inviare i dati serializzati sia su un file sia su un canale standard.

// Comunicazione su file XML
std::fstream os("cereal.xml");
cereal::XMLOutputArchive write_archive( os );
cereal::XMLInputArchive read_archive( os );

// Comunicazione tramite canali standard
cereal::XMLOutputArchive write_archive( std::cout );
cereal::XMLInputArchive read_archive( std::cin );

Serializzare variabili semplici

stringa = "mia stringa";
carattere = 'x';
intero = 42;
        
write_archive(
    CEREAL_NVP(stringa),
    CEREAL_NVP(carattere),
    CEREAL_NVP(intero)
);

Dall'esecuzione si ottiene un file xml contenente:

<?xml version="1.0" encoding="utf-8"?>
<cereal>
        <stringa>mia stringa</stringa>
        <carattere>x</carattere>
        <intero>42</intero>
</cereal>

Per leggere il file serializzato:

read_archive(CEREAL_NVP(intero));
std::cout << "Intero:    " << intero << std::endl;

read_archive(CEREAL_NVP(carattere));
std::cout << "Carattere: " << carattere << std::endl;

read_archive(CEREAL_NVP(stringa));
std::cout << "Stringa:   " << stringa << std::endl;

Serializzare un contenitore standard

La libreria fornisce strumenti per serializzare in modo automatico dei contenitori noti della STL e delle BOOST, basta aggiungere il corretto file header.

#include <iostream>
#include <cereal/archives/xml.hpp>
#include <cereal/types/vector.hpp>

int main() {

   cereal::XMLOutputArchive archive( std::cout );
   std::vector<int> vec = {1, 2, 3, 4, 5};

   archive(
      CEREAL_NVP(vec)
   );

}

Che fornisce il seguente output:

<?xml version="1.0" encoding="utf-8"?>
<cereal>
        <vec size="dynamic">
                <value0>1</value0>
                <value1>2</value1>
                <value2>3</value2>
                <value3>4</value3>
                <value4>5</value4>
        </vec>
</cereal>

Serializzare una propria classe

Dato che nel C++ la reflection è molto limitata, per serializzare una classe custom è necessario specificare come trattarla. Questo può essere fatto definendo la funzione serialize, che può essere un metodo interno alla classe o definita esternamente. E' anche possibile specificare le singole funzioni save e load se necessario.

Definizione interna

class myClass {
public:
   int a;
   int b;

   template<class Archive>
   void serialize(Archive & archive) {
      archive( 
         CEREAL_NVP(a),
         CEREAL_NVP(b)
      ); 
   }

};

Definizione esterna

class myClass {
public:
   int a;
   int b;
};

template<class Archive>
void serialize(Archive & archive, myClass & m) {
   archive( 
      CEREAL_NVP(m.a),
      CEREAL_NVP(m.b)
   ); 
}

Output

<?xml version="1.0" encoding="utf-8"?>
<cereal>
        <myObj>
                <m.a>1</m.a>
                <m.b>2</m.b>
        </myObj>
</cereal>