mirror of
https://github.com/paboyle/Grid.git
synced 2025-06-10 19:36:56 +01:00
XMLReader implementation and a virtual Reader/Writer template framework.
Test_serialisation has an example of *code* *free* object serialisation to both ostream and to XML using macro magic. Implementing TextReader/TextWriter, YAML, JSON etc.. should be trivial and we can use configure time options to select the default "Reader" typedef. Present done with "using XMLPolicy::Reader" to pick up the default serialisation strategy.
This commit is contained in:
100
lib/serialisation/MacroMagic.h
Normal file
100
lib/serialisation/MacroMagic.h
Normal file
@ -0,0 +1,100 @@
|
||||
#ifndef GRID_MACRO_MAGIC_H
|
||||
#define GRID_MACRO_MAGIC_H
|
||||
|
||||
#define strong_inline __attribute__((always_inline)) inline
|
||||
|
||||
#ifndef MAX
|
||||
#define MAX(x,y) ((x)>(y)?(x):(y))
|
||||
#define MIN(x,y) ((x)>(y)?(y):(x))
|
||||
#endif
|
||||
|
||||
#define GRID_MACRO_FIRST(a, ...) a
|
||||
#define GRID_MACRO_SECOND(a, b, ...) b
|
||||
|
||||
#define GRID_MACRO_EMPTY()
|
||||
|
||||
#define GRID_MACRO_EVAL(...) GRID_MACRO_EVAL1024(__VA_ARGS__)
|
||||
#define GRID_MACRO_EVAL1024(...) GRID_MACRO_EVAL512(GRID_MACRO_EVAL512(__VA_ARGS__))
|
||||
#define GRID_MACRO_EVAL512(...) GRID_MACRO_EVAL256(GRID_MACRO_EVAL256(__VA_ARGS__))
|
||||
#define GRID_MACRO_EVAL256(...) GRID_MACRO_EVAL128(GRID_MACRO_EVAL128(__VA_ARGS__))
|
||||
#define GRID_MACRO_EVAL128(...) GRID_MACRO_EVAL64(GRID_MACRO_EVAL64(__VA_ARGS__))
|
||||
#define GRID_MACRO_EVAL64(...) GRID_MACRO_EVAL32(GRID_MACRO_EVAL32(__VA_ARGS__))
|
||||
#define GRID_MACRO_EVAL32(...) GRID_MACRO_EVAL16(GRID_MACRO_EVAL16(__VA_ARGS__))
|
||||
#define GRID_MACRO_EVAL16(...) GRID_MACRO_EVAL8(GRID_MACRO_EVAL8(__VA_ARGS__))
|
||||
#define GRID_MACRO_EVAL8(...) GRID_MACRO_EVAL4(GRID_MACRO_EVAL4(__VA_ARGS__))
|
||||
#define GRID_MACRO_EVAL4(...) GRID_MACRO_EVAL2(GRID_MACRO_EVAL2(__VA_ARGS__))
|
||||
#define GRID_MACRO_EVAL2(...) GRID_MACRO_EVAL1(GRID_MACRO_EVAL1(__VA_ARGS__))
|
||||
#define GRID_MACRO_EVAL1(...) __VA_ARGS__
|
||||
|
||||
#define GRID_MACRO_DEFER1(m) m GRID_MACRO_EMPTY()
|
||||
#define GRID_MACRO_DEFER2(m) m GRID_MACRO_EMPTY GRID_MACRO_EMPTY()()
|
||||
#define GRID_MACRO_DEFER3(m) m GRID_MACRO_EMPTY GRID_MACRO_EMPTY GRID_MACRO_EMPTY()()()
|
||||
#define GRID_MACRO_DEFER4(m) m GRID_MACRO_EMPTY GRID_MACRO_EMPTY GRID_MACRO_EMPTY GRID_MACRO_EMPTY()()()()
|
||||
|
||||
#define GRID_MACRO_IS_PROBE(...) GRID_MACRO_SECOND(__VA_ARGS__, 0)
|
||||
#define GRID_MACRO_PROBE() ~, 1
|
||||
|
||||
#define GRID_MACRO_CAT(a,b) a ## b
|
||||
|
||||
#define GRID_MACRO_NOT(x) GRID_MACRO_IS_PROBE(GRID_MACRO_CAT(_GRID_MACRO_NOT_, x))
|
||||
#define _GRID_MACRO_NOT_0 GRID_MACRO_PROBE()
|
||||
|
||||
#define GRID_MACRO_BOOL(x) GRID_MACRO_NOT(GRID_MACRO_NOT(x))
|
||||
|
||||
#define GRID_MACRO_IF_ELSE(condition) _GRID_MACRO_IF_ELSE(GRID_MACRO_BOOL(condition))
|
||||
#define _GRID_MACRO_IF_ELSE(condition) GRID_MACRO_CAT(_GRID_MACRO_IF_, condition)
|
||||
|
||||
#define _GRID_MACRO_IF_1(...) __VA_ARGS__ _GRID_MACRO_IF_1_ELSE
|
||||
#define _GRID_MACRO_IF_0(...) _GRID_MACRO_IF_0_ELSE
|
||||
|
||||
#define _GRID_MACRO_IF_1_ELSE(...)
|
||||
#define _GRID_MACRO_IF_0_ELSE(...) __VA_ARGS__
|
||||
|
||||
#define GRID_MACRO_HAS_ARGS(...) GRID_MACRO_BOOL(GRID_MACRO_FIRST(_GRID_MACRO_END_OF_ARGUMENTS_ __VA_ARGS__)())
|
||||
#define _GRID_MACRO_END_OF_ARGUMENTS_() 0
|
||||
|
||||
#define GRID_MACRO_MAP(m, first, second, ...) \
|
||||
m(first,second) \
|
||||
GRID_MACRO_IF_ELSE(GRID_MACRO_HAS_ARGS(__VA_ARGS__))( \
|
||||
GRID_MACRO_DEFER4(_GRID_MACRO_MAP)()(m, __VA_ARGS__) \
|
||||
)( \
|
||||
/* Do nothing, just terminate */ \
|
||||
)
|
||||
|
||||
#define _GRID_MACRO_MAP() GRID_MACRO_MAP
|
||||
|
||||
#define GRID_MACRO_MEMBER(A,B) A B;
|
||||
|
||||
#define GRID_MACRO_OS_WRITE_MEMBER(A,B) os<< #A <<" "#B <<" = "<< obj. B <<" ; " <<std::endl;
|
||||
#define GRID_MACRO_READ_MEMBER(A,B) read(RD,#B,obj. B);
|
||||
#define GRID_MACRO_WRITE_MEMBER(A,B) write(WR,#B,obj. B);
|
||||
|
||||
#define GRID_DECL_CLASS_MEMBERS(cname,...) \
|
||||
\
|
||||
\
|
||||
GRID_MACRO_EVAL(GRID_MACRO_MAP(GRID_MACRO_MEMBER,__VA_ARGS__)) \
|
||||
\
|
||||
\
|
||||
template<class Writer> friend void write(Writer &WR,const std::string &s, const cname &obj){ \
|
||||
push(WR,s);\
|
||||
GRID_MACRO_EVAL(GRID_MACRO_MAP(GRID_MACRO_WRITE_MEMBER,__VA_ARGS__)) \
|
||||
pop(WR);\
|
||||
} \
|
||||
\
|
||||
\
|
||||
template<class Reader> friend void read(Reader &RD,const std::string &s, cname &obj){ \
|
||||
push(RD,s);\
|
||||
GRID_MACRO_EVAL(GRID_MACRO_MAP(GRID_MACRO_READ_MEMBER,__VA_ARGS__)) \
|
||||
pop(RD);\
|
||||
} \
|
||||
\
|
||||
\
|
||||
friend std::ostream & operator << (std::ostream &os, const cname &obj ) { \
|
||||
os<<"class "<<#cname<<" {"<<std::endl;\
|
||||
GRID_MACRO_EVAL(GRID_MACRO_MAP(GRID_MACRO_OS_WRITE_MEMBER,__VA_ARGS__)) \
|
||||
os<<"}"; \
|
||||
return os;\
|
||||
};
|
||||
|
||||
|
||||
#endif
|
81
lib/serialisation/Reader.h
Normal file
81
lib/serialisation/Reader.h
Normal file
@ -0,0 +1,81 @@
|
||||
#ifndef GRID_SERIALISATION_READER_H
|
||||
#define GRID_SERIALISATION_READER_H
|
||||
|
||||
#include <serialisation/MacroMagic.h>
|
||||
|
||||
namespace Grid {
|
||||
|
||||
// Generic reader writer interface
|
||||
|
||||
template< class Writer> void push(Writer & WR,const std::string &s) { WR.push(s);}
|
||||
template< class Writer> void push(Writer & WR,const char *s) { WR.push(std::string(s));}
|
||||
template< class Writer> void pop (Writer & WR) { WR.pop();}
|
||||
|
||||
template< class Writer> void write(Writer& wr, const std::string& s,const char * output ) { wr.iwrite(s,std::string(output)); };
|
||||
template< class Writer> void write(Writer& wr, const std::string& s,const std::string &output) { wr.iwrite(s,output); };
|
||||
template< class Writer> void write(Writer& wr, const std::string& s, int16_t output ) { wr.iwrite(s,output); };
|
||||
template< class Writer> void write(Writer& wr, const std::string& s, uint16_t output ) { wr.iwrite(s,output); };
|
||||
template< class Writer> void write(Writer& wr, const std::string& s, int32_t output ) { wr.iwrite(s,output); };
|
||||
template< class Writer> void write(Writer& wr, const std::string& s, uint32_t output ) { wr.iwrite(s,output); };
|
||||
template< class Writer> void write(Writer& wr, const std::string& s, int64_t output ) { wr.iwrite(s,output); };
|
||||
template< class Writer> void write(Writer& wr, const std::string& s, uint64_t output ) { wr.iwrite(s,output); };
|
||||
template< class Writer> void write(Writer& wr, const std::string& s, float output ) { wr.iwrite(s,output); };
|
||||
template< class Writer> void write(Writer& wr, const std::string& s, double output ) { wr.iwrite(s,output); };
|
||||
template< class Writer> void write(Writer& wr, const std::string& s, bool output ) { wr.iwrite(s,output); };
|
||||
|
||||
template< class Reader> void read(Reader& rd, const std::string& s,std::string &output) { rd.iread(s,output); };
|
||||
template< class Reader> void read(Reader& rd, const std::string& s, int16_t &output ) { rd.iread(s,output); };
|
||||
template< class Reader> void read(Reader& rd, const std::string& s, uint16_t &output ) { rd.iread(s,output); };
|
||||
template< class Reader> void read(Reader& rd, const std::string& s, int32_t &output ) { rd.iread(s,output); };
|
||||
template< class Reader> void read(Reader& rd, const std::string& s, uint32_t &output ) { rd.iread(s,output); };
|
||||
template< class Reader> void read(Reader& rd, const std::string& s, int64_t &output ) { rd.iread(s,output); };
|
||||
template< class Reader> void read(Reader& rd, const std::string& s, uint64_t &output ) { rd.iread(s,output); };
|
||||
template< class Reader> void read(Reader& rd, const std::string& s, float &output ) { rd.iread(s,output); };
|
||||
template< class Reader> void read(Reader& rd, const std::string& s, double &output ) { rd.iread(s,output); };
|
||||
template< class Reader> void read(Reader& rd, const std::string& s, bool &output ) { rd.iread(s,output); };
|
||||
|
||||
|
||||
template<class Writer, class T>
|
||||
void write(Writer& wr, const std::string& s,const std::vector<T> output ) {
|
||||
push(wr,s);
|
||||
for(int i=0;i<output.size();i++){
|
||||
std::ostringstream oss; oss << "elem" << i;
|
||||
write(wr,oss.str(),output[i]);
|
||||
}
|
||||
pop(wr);
|
||||
};
|
||||
|
||||
template<class Reader, class T>
|
||||
void read(Reader& rd, const std::string& s,std::vector<T> &output ) {
|
||||
rd.iread(s,output);
|
||||
};
|
||||
|
||||
template < class T >
|
||||
inline std::ostream& operator << (std::ostream& os, const std::vector<T>& v)
|
||||
{
|
||||
os << "[";
|
||||
for (typename std::vector<T>::const_iterator ii = v.begin(); ii != v.end(); ++ii)
|
||||
{
|
||||
os << " " << *ii;
|
||||
}
|
||||
os << " ]";
|
||||
return os;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// Todo:
|
||||
//#include <serialisation/CoutReader.h>
|
||||
//#include <serialisation/TextReader.h>
|
||||
//#include <serialisation/JSONReader.h>
|
||||
//#include <serialisation/YAMLReader.h>
|
||||
#include <serialisation/XMLReader.h>
|
||||
|
||||
namespace Grid {
|
||||
|
||||
using XMLPolicy::Reader;
|
||||
using XMLPolicy::Writer;
|
||||
|
||||
}
|
||||
|
||||
#endif
|
168
lib/serialisation/XMLReader.h
Normal file
168
lib/serialisation/XMLReader.h
Normal file
@ -0,0 +1,168 @@
|
||||
#ifndef GRID_SERIALISATION_XML_READER_H
|
||||
#define GRID_SERIALISATION_XML_READER_H
|
||||
|
||||
#include <iostream>
|
||||
#include <iomanip>
|
||||
#include <fstream>
|
||||
#include <sstream>
|
||||
#include <math.h>
|
||||
#include <vector>
|
||||
#include <cassert>
|
||||
|
||||
#include "pugixml/pugixml.h"
|
||||
|
||||
|
||||
namespace Grid {
|
||||
|
||||
class XMLWriter {
|
||||
private:
|
||||
|
||||
pugi::xml_document doc;
|
||||
pugi::xml_node node;
|
||||
std::string file;
|
||||
|
||||
public:
|
||||
|
||||
XMLWriter(const std::string &_file) : file(_file)
|
||||
{
|
||||
node=doc.append_child();
|
||||
node.set_name("document");
|
||||
}
|
||||
|
||||
~XMLWriter()
|
||||
{
|
||||
// simple_walker walker;
|
||||
// doc.traverse(walker);
|
||||
|
||||
doc.save_file(file.c_str()," ");
|
||||
}
|
||||
|
||||
void push(const std::string &s)
|
||||
{
|
||||
node = node.append_child(s.c_str());
|
||||
}
|
||||
void pop(void) {
|
||||
node = node.parent();
|
||||
}
|
||||
|
||||
void iwrite( const std::string& s,const std::string &output ) {
|
||||
pugi::xml_node leaf=node.append_child(s.c_str());
|
||||
leaf.append_child(pugi::node_pcdata).set_value(output.c_str());
|
||||
};
|
||||
void iwrite( const std::string& s, int16_t output ) { writeInternal(s,output); };
|
||||
void iwrite( const std::string& s, uint16_t output ) { writeInternal(s,output); };
|
||||
void iwrite( const std::string& s, int32_t output ) { writeInternal(s,output); };
|
||||
void iwrite( const std::string& s, uint32_t output ) { writeInternal(s,output); };
|
||||
void iwrite( const std::string& s, int64_t output ) { writeInternal(s,output); };
|
||||
void iwrite( const std::string& s, uint64_t output ) { writeInternal(s,output); };
|
||||
void iwrite( const std::string& s, float output ) { writeInternal(s,output); };
|
||||
void iwrite( const std::string& s, double output ) { writeInternal(s,output); };
|
||||
void iwrite( const std::string& s, bool output ) { writeInternal(s,output); };
|
||||
|
||||
private:
|
||||
template<class T> void writeInternal( const std::string& s, T output ){
|
||||
std::ostringstream os;
|
||||
os << std::boolalpha << output;
|
||||
iwrite(s,os.str());
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
|
||||
class XMLReader {
|
||||
private:
|
||||
|
||||
pugi::xml_document doc;
|
||||
pugi::xml_node node;
|
||||
|
||||
public:
|
||||
|
||||
|
||||
XMLReader(const std::string &_file)
|
||||
{
|
||||
pugi::xml_parse_result result = doc.load_file(_file.c_str());
|
||||
|
||||
if ( !result ) {
|
||||
std::cout << "XML error description: " << result.description() << "\n";
|
||||
std::cout << "XML error offset: " << result.offset << "\n";
|
||||
}
|
||||
|
||||
assert(result);
|
||||
|
||||
// simple_walker walker;
|
||||
// doc.traverse(walker);
|
||||
|
||||
node= doc.child("document");
|
||||
}
|
||||
|
||||
~XMLReader()
|
||||
{
|
||||
}
|
||||
|
||||
void iread( const std::string& s,std::string &output ) {
|
||||
output=node.child(s.c_str()).first_child().value();
|
||||
};
|
||||
void push(const std::string &s)
|
||||
{
|
||||
node = node.child(s.c_str());
|
||||
}
|
||||
void pop(void) {
|
||||
node = node.parent();
|
||||
}
|
||||
|
||||
template<class T>
|
||||
void iread( const std::string& s, std::vector<T> &output ) {
|
||||
output.resize(0);
|
||||
|
||||
T tmp;
|
||||
push(s);
|
||||
int i=0;
|
||||
for(pugi::xml_node it=node.first_child(); it; it = it.next_sibling() ){
|
||||
std::ostringstream oss; oss << "elem" << i;
|
||||
read(*this,oss.str(),tmp);
|
||||
output.push_back(tmp);
|
||||
i++;
|
||||
}
|
||||
pop();
|
||||
|
||||
};
|
||||
|
||||
void iread( const std::string& s, int16_t &output ) { readInternal(s,output); };
|
||||
void iread( const std::string& s, uint16_t &output ) { readInternal(s,output); };
|
||||
void iread( const std::string& s, int32_t &output ) { readInternal(s,output); };
|
||||
void iread( const std::string& s, uint32_t &output ) { readInternal(s,output); };
|
||||
void iread( const std::string& s, int64_t &output ) { readInternal(s,output); };
|
||||
void iread( const std::string& s, uint64_t &output ) { readInternal(s,output); };
|
||||
void iread( const std::string& s, float &output ) { readInternal(s,output); };
|
||||
void iread( const std::string& s, double &output ) { readInternal(s,output); };
|
||||
void iread( const std::string& s, bool &output ) { readInternal(s,output); };
|
||||
|
||||
|
||||
private:
|
||||
|
||||
template<class T> void readInternal( const std::string& path, T &output ){
|
||||
std::string asString;
|
||||
iread(path,asString);
|
||||
convert(asString,output);
|
||||
}
|
||||
|
||||
template<class T> void convert(const std::string &asString,T &output)
|
||||
{
|
||||
std::istringstream is(asString); is.exceptions(std::ios::failbit);
|
||||
try {
|
||||
is >> std::boolalpha >> output;
|
||||
} catch(std::istringstream::failure e) {
|
||||
std::cerr << "XML read failure on "<<" "<<asString<<" "<<typeid(T).name()<<std::endl;
|
||||
}
|
||||
assert( is.tellg()==-1);
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
namespace XMLPolicy
|
||||
{
|
||||
typedef XMLReader Reader;
|
||||
typedef XMLWriter Writer;
|
||||
};
|
||||
}
|
||||
#endif
|
Reference in New Issue
Block a user