diff --git a/.gitignore b/.gitignore index 12bb4c5b..d40d0a86 100644 --- a/.gitignore +++ b/.gitignore @@ -44,6 +44,7 @@ Makefile.in Makefile Config.h +Config.h.in config.log config.status .deps diff --git a/lib/serialisation/BaseIO.h b/lib/serialisation/BaseIO.h index 200b8ee3..60e3e3af 100644 --- a/lib/serialisation/BaseIO.h +++ b/lib/serialisation/BaseIO.h @@ -22,7 +22,12 @@ namespace Grid { typename std::enable_if::value, void>::type write(const std::string& s, const U &output); template - typename std::enable_if::value, void>::type + typename std::enable_if::value, void>::type + write(const std::string& s, const U &output); + template + typename std::enable_if< + !(std::is_base_of::value or std::is_enum::value), + void>::type write(const std::string& s, const U &output); private: T *upcast; @@ -41,7 +46,12 @@ namespace Grid { typename std::enable_if::value, void>::type read(const std::string& s, U &output); template - typename std::enable_if::value, void>::type + typename std::enable_if::value, void>::type + read(const std::string& s, U &output); + template + typename std::enable_if< + !(std::is_base_of::value or std::is_enum::value), + void>::type read(const std::string& s, U &output); protected: template @@ -146,7 +156,17 @@ namespace Grid { template template - typename std::enable_if::value, void>::type + typename std::enable_if::value, void>::type + Writer::write(const std::string &s, const U &output) + { + EnumIO::write(*this, s, output); + } + + template + template + typename std::enable_if< + !(std::is_base_of::value or std::is_enum::value), + void>::type Writer::write(const std::string &s, const U &output) { upcast->writeDefault(s, output); @@ -181,7 +201,17 @@ namespace Grid { template template - typename std::enable_if::value, void>::type + typename std::enable_if::value, void>::type + Reader::read(const std::string &s, U &output) + { + EnumIO::read(*this, s, output); + } + + template + template + typename std::enable_if< + !(std::is_base_of::value or std::is_enum::value), + void>::type Reader::read(const std::string &s, U &output) { upcast->readDefault(s, output); @@ -205,7 +235,7 @@ namespace Grid { abort(); } } - + } #endif diff --git a/lib/serialisation/BinaryIO.cc b/lib/serialisation/BinaryIO.cc index f546ddb4..250285e5 100644 --- a/lib/serialisation/BinaryIO.cc +++ b/lib/serialisation/BinaryIO.cc @@ -1,36 +1,43 @@ #include +using namespace Grid; +using namespace std; -namespace Grid { // Writer implementation /////////////////////////////////////////////////////// -BinaryWriter::BinaryWriter(const std::string &fileName) -: file_(fileName, std::ios::binary|std::ios::out) +BinaryWriter::BinaryWriter(const string &fileName) +: file_(fileName, ios::binary|ios::out) {} template <> -void BinaryWriter::writeDefault(const std::string &s, const std::string &output) +void BinaryWriter::writeDefault(const string &s, const string &x) { - uint64_t sz = output.size(); + uint64_t sz = x.size(); + + write("", sz); + for (uint64_t i = 0; i < sz; ++i) + { + write("", x[i]); + } +} + +void BinaryWriter::writeDefault(const string &s, const char *x) +{ + string sx(x); - write("", sz); - for (uint64_t i = 0; i < sz; ++i) - { - write("", output[i]); - } + writeDefault(s, sx); } // Reader implementation /////////////////////////////////////////////////////// -BinaryReader::BinaryReader(const std::string &fileName) -: file_(fileName, std::ios::binary|std::ios::in) +BinaryReader::BinaryReader(const string &fileName) +: file_(fileName, ios::binary|ios::in) {} template <> -void BinaryReader::readDefault(const std::string &s, std::string &output) +void BinaryReader::readDefault(const string &s, string &output) { - uint64_t sz; + uint64_t sz; - read("", sz); - output.reserve(sz); - file_.read((char *)output.data(), sz); -} + read("", sz); + output.resize(sz); + file_.read((char *)output.data(), sz); } diff --git a/lib/serialisation/BinaryIO.h b/lib/serialisation/BinaryIO.h index 004ab9a8..f0cfb941 100644 --- a/lib/serialisation/BinaryIO.h +++ b/lib/serialisation/BinaryIO.h @@ -22,6 +22,7 @@ namespace Grid { void writeDefault(const std::string &s, const U &x); template void writeDefault(const std::string &s, const std::vector &x); + void writeDefault(const std::string &s, const char *x); private: std::ofstream file_; }; @@ -48,6 +49,9 @@ namespace Grid { file_.write((char *)&x, sizeof(U)); } + template <> + void BinaryWriter::writeDefault(const std::string &s, const std::string &x); + template void BinaryWriter::writeDefault(const std::string &s, const std::vector &x) { @@ -67,6 +71,9 @@ namespace Grid { file_.read((char *)&output, sizeof(U)); } + template <> + void BinaryReader::readDefault(const std::string &s, std::string &output); + template void BinaryReader::readDefault(const std::string &s, std::vector &output) { diff --git a/lib/serialisation/MacroMagic.h b/lib/serialisation/MacroMagic.h index ee497ce4..34fd893f 100644 --- a/lib/serialisation/MacroMagic.h +++ b/lib/serialisation/MacroMagic.h @@ -109,12 +109,11 @@ THE SOFTWARE. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// #define GRID_MACRO_MEMBER(A,B) A B; - #define GRID_MACRO_OS_WRITE_MEMBER(A,B) os<< #A <<" "#B <<" = "<< obj. B <<" ; " <::type +#define GRID_MACRO_ENUMVAL(A,B) A = B, +#define GRID_MACRO_ENUMCASE(A,B) case GRID_ENUM_TYPE(obj)::A: Grid::write(WR,s,#A); break; +#define GRID_MACRO_ENUMTEST(A,B) else if (buf == #A) {obj = GRID_ENUM_TYPE(obj)::A;} +#define GRID_MACRO_ENUMCASEIO(A,B) case GRID_ENUM_TYPE(obj)::A: os << #A; break; + +namespace Grid { + template + class EnumIO {}; +} + +#define GRID_SERIALIZABLE_ENUM(name,undefname,...)\ + enum class name {\ + GRID_MACRO_EVAL(GRID_MACRO_MAP(GRID_MACRO_ENUMVAL,__VA_ARGS__))\ + undefname = -1\ + };\ + \ + template<>\ + class EnumIO {\ + public:\ + template \ + static void write(Writer &WR,const std::string &s, const name &obj){ \ + switch (obj) {\ + GRID_MACRO_EVAL(GRID_MACRO_MAP(GRID_MACRO_ENUMCASE,__VA_ARGS__))\ + default: Grid::write(WR,s,#undefname); break;\ + }\ + }\ + \ + template \ + static void read(Reader &RD,const std::string &s, name &obj){ \ + std::string buf;\ + Grid::read(RD, s, buf);\ + if (buf == #undefname) {obj = name::undefname;}\ + GRID_MACRO_EVAL(GRID_MACRO_MAP(GRID_MACRO_ENUMTEST,__VA_ARGS__))\ + else {obj = name::undefname;}\ + }\ + };\ + \ + std::ostream & operator << (std::ostream &os, const name &obj ) { \ + switch (obj) {\ + GRID_MACRO_EVAL(GRID_MACRO_MAP(GRID_MACRO_ENUMCASEIO,__VA_ARGS__))\ + default: os << #undefname; break;\ + }\ + return os;\ + }; + #endif diff --git a/lib/serialisation/TextIO.cc b/lib/serialisation/TextIO.cc index 8b9c4f01..a1caa8db 100644 --- a/lib/serialisation/TextIO.cc +++ b/lib/serialisation/TextIO.cc @@ -1,12 +1,14 @@ #include -namespace Grid { +using namespace Grid; +using namespace std; + // Writer implementation /////////////////////////////////////////////////////// -TextWriter::TextWriter(const std::string &fileName) -: file_(fileName, std::ios::out) +TextWriter::TextWriter(const string &fileName) +: file_(fileName, ios::out) {} -void TextWriter::push(const std::string &s) +void TextWriter::push(const string &s) { level_++; }; @@ -25,11 +27,11 @@ void TextWriter::indent(void) }; // Reader implementation /////////////////////////////////////////////////////// -TextReader::TextReader(const std::string &fileName) -: file_(fileName, std::ios::in) +TextReader::TextReader(const string &fileName) +: file_(fileName, ios::in) {} -void TextReader::push(const std::string &s) +void TextReader::push(const string &s) { level_++; }; @@ -48,9 +50,9 @@ void TextReader::checkIndent(void) file_.get(c); if (c != '\t') { - std::cerr << "mismatch on tab " << c << " level " << level_; - std::cerr << " i "<< i < void TextReader::readDefault(const std::string &s, std::string &output) { - checkIndent(); - output.clear(); - getline(file_, output); -} + checkIndent(); + output.clear(); + getline(file_, output); } diff --git a/lib/serialisation/TextIO.h b/lib/serialisation/TextIO.h index 9b69b188..a60931d1 100644 --- a/lib/serialisation/TextIO.h +++ b/lib/serialisation/TextIO.h @@ -20,9 +20,9 @@ namespace Grid void push(const std::string &s); void pop(void); template - void writeDefault(const std::string &s, const U &output); + void writeDefault(const std::string &s, const U &x); template - void writeDefault(const std::string &s, const std::vector &output); + void writeDefault(const std::string &s, const std::vector &x); private: void indent(void); private: @@ -50,21 +50,21 @@ namespace Grid // Writer template implementation //////////////////////////////////////////// template - void TextWriter::writeDefault(const std::string &s, const U &output) + void TextWriter::writeDefault(const std::string &s, const U &x) { indent(); - file_ << std::boolalpha << output << std::endl; + file_ << std::boolalpha << x << std::endl; } template - void TextWriter::writeDefault(const std::string &s, const std::vector &output) + void TextWriter::writeDefault(const std::string &s, const std::vector &x) { - uint64_t sz = output.size(); + uint64_t sz = x.size(); write(s, sz); for (uint64_t i = 0; i < sz; ++i) { - write(s, output[i]); + write(s, x[i]); } } @@ -78,6 +78,9 @@ namespace Grid fromString(output, buf); } + template <> + void TextReader::readDefault(const std::string &s, std::string &output); + template void TextReader::readDefault(const std::string &s, std::vector &output) { diff --git a/lib/serialisation/XmlIO.cc b/lib/serialisation/XmlIO.cc index b5c6e5bd..8dd93de7 100644 --- a/lib/serialisation/XmlIO.cc +++ b/lib/serialisation/XmlIO.cc @@ -1,8 +1,10 @@ #include -namespace Grid { +using namespace Grid; +using namespace std; + // Writer implementation /////////////////////////////////////////////////////// -XmlWriter::XmlWriter(const std::string &fileName) +XmlWriter::XmlWriter(const string &fileName) : fileName_(fileName) { node_ = doc_.append_child(); @@ -14,7 +16,7 @@ XmlWriter::~XmlWriter(void) doc_.save_file(fileName_.c_str(), " "); } -void XmlWriter::push(const std::string &s) +void XmlWriter::push(const string &s) { node_ = node_.append_child(s.c_str()); } @@ -25,22 +27,22 @@ void XmlWriter::pop(void) } // Reader implementation /////////////////////////////////////////////////////// -XmlReader::XmlReader(const std::string &fileName) +XmlReader::XmlReader(const string &fileName) : fileName_(fileName) { pugi::xml_parse_result result = doc_.load_file(fileName_.c_str()); if ( !result ) { - std::cerr << "XML error description: " << result.description() << "\n"; - std::cerr << "XML error offset : " << result.offset << "\n"; - std::abort(); + cerr << "XML error description: " << result.description() << "\n"; + cerr << "XML error offset : " << result.offset << "\n"; + abort(); } node_ = doc_.child("grid"); } -void XmlReader::push(const std::string &s) +void XmlReader::push(const string &s) { node_ = node_.child(s.c_str()); } @@ -51,8 +53,7 @@ void XmlReader::pop(void) } template <> -void XmlReader::readDefault(const std::string &s, std::string &output) +void XmlReader::readDefault(const string &s, string &output) { output = node_.child(s.c_str()).first_child().value(); } -} diff --git a/lib/serialisation/XmlIO.h b/lib/serialisation/XmlIO.h index 45fc6fac..15bb0206 100644 --- a/lib/serialisation/XmlIO.h +++ b/lib/serialisation/XmlIO.h @@ -81,10 +81,12 @@ namespace Grid fromString(output, buf); } + template <> + void XmlReader::readDefault(const std::string &s, std::string &output); + template void XmlReader::readDefault(const std::string &s, std::vector &output) { - pugi::xml_node nodeCpy; std::string buf; unsigned int i = 0; @@ -96,7 +98,6 @@ namespace Grid node_.child("elem").set_name("elem-done"); i++; } - // assert( is.tellg()==-1); pop(); } diff --git a/tests/Test_dwf_hdcr.cc b/tests/Test_dwf_hdcr.cc index 006d0e5e..469e6cc4 100644 --- a/tests/Test_dwf_hdcr.cc +++ b/tests/Test_dwf_hdcr.cc @@ -9,7 +9,7 @@ using namespace Grid::QCD; class myclass: Serializable { public: - GRID_DECL_CLASS_MEMBERS(myclass, + GRID_SERIALIZABLE_CLASS_MEMBERS(myclass, int, domaindecompose, int, domainsize, int, order, diff --git a/tests/Test_serialisation.cc b/tests/Test_serialisation.cc index cfb4b8e7..5ab85181 100644 --- a/tests/Test_serialisation.cc +++ b/tests/Test_serialisation.cc @@ -1,30 +1,39 @@ #include namespace Grid { + + GRID_SERIALIZABLE_ENUM(myenum, undef, red, 1, blue, 2, green, 3); + class myclass: Serializable { public: - GRID_DECL_CLASS_MEMBERS(myclass, + GRID_SERIALIZABLE_CLASS_MEMBERS(myclass, + myenum, e, + std::vector, ve, + std::string, name, int, x, double, y, bool , b, - std::string, name, std::vector, array, std::vector>, twodimarray, ); myclass() {} myclass(int i) - : array(4,5.1), twodimarray(3,std::vector(2,1.23456)) + : array(4,5.1), twodimarray(3,std::vector(2,1.23456)), ve(2, myenum::blue) { + e=myenum::red; x=i; y=2*i; b=true; name="bother said pooh"; } }; + } +using namespace Grid; + int16_t i16 = 1; uint16_t u16 = 2; int32_t i32 = 3; @@ -35,8 +44,6 @@ float f = M_PI; double d = 2*M_PI; bool b = false; -using namespace Grid; - int main(int argc,char **argv) { { @@ -59,6 +66,7 @@ int main(int argc,char **argv) myclass obj(1234); // non-trivial constructor write(WR,"obj",obj); WR.write("obj2", obj); + std::cout << obj << std::endl; std::vector vec; vec.push_back(myclass(1234));