/************************************************************************************* Grid physics library, www.github.com/paboyle/Grid Source file: ./lib/serialisation/BaseIO.h Copyright (C) 2015 Author: Antonin Portelli Author: Peter Boyle This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. See the full license in the file "LICENSE" in the top level distribution directory *************************************************************************************/ /* END LEGAL */ #ifndef GRID_SERIALISATION_ABSTRACT_READER_H #define GRID_SERIALISATION_ABSTRACT_READER_H #include namespace Grid { // helper function to read space-separated values template std::vector strToVec(const std::string s) { std::istringstream sstr(s); T buf; std::vector v; while(!sstr.eof()) { sstr >> buf; v.push_back(buf); } return v; } // output to streams for vectors template < class T > inline std::ostream & operator<<(std::ostream &os, const std::vector &v) { os << "["; for (auto &x: v) { os << x << " "; } if (v.size() > 0) { os << "\b"; } os << "]"; return os; } class Serializable {}; // static polymorphism implemented using CRTP idiom // Static abstract writer template class Writer { public: Writer(void); virtual ~Writer(void) = default; void push(const std::string &s); void pop(void); template typename std::enable_if::value, void>::type write(const std::string& s, const U &output); template 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; }; // Static abstract reader template class Reader { public: Reader(void); virtual ~Reader(void) = default; void push(const std::string &s); void pop(void); template typename std::enable_if::value, void>::type read(const std::string& s, U &output); template 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 void fromString(U &output, const std::string &s); private: T *upcast; }; // Generic writer interface template inline void push(Writer &w, const std::string &s) { w.push(s); } template inline void push(Writer &w, const char *s) { w.push(std::string(s)); } template inline void pop(Writer &w) { w.pop(); } template inline void write(Writer &w, const std::string& s, const U &output) { w.write(s, output); } // Generic reader interface template inline void push(Reader &r, const std::string &s) { r.push(s); } template inline void push(Reader &r, const char *s) { r.push(std::string(s)); } template inline void pop(Reader &r) { r.pop(); } template inline void read(Reader &r, const std::string &s, U &output) { r.read(s, output); } // Writer template implementation //////////////////////////////////////////// template Writer::Writer(void) { upcast = static_cast(this); } template void Writer::push(const std::string &s) { upcast->push(s); } template void Writer::pop(void) { upcast->pop(); } template template typename std::enable_if::value, void>::type Writer::write(const std::string &s, const U &output) { U::write(*this, s, output); } template template 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); } // Reader template implementation //////////////////////////////////////////// template Reader::Reader(void) { upcast = static_cast(this); } template void Reader::push(const std::string &s) { upcast->push(s); } template void Reader::pop(void) { upcast->pop(); } template template typename std::enable_if::value, void>::type Reader::read(const std::string &s, U &output) { U::read(*this, s, output); } template template 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); } template template void Reader::fromString(U &output, const std::string &s) { std::istringstream is(s); is.exceptions(std::ios::failbit); try { is >> std::boolalpha >> output; } catch(std::istringstream::failure &e) { std::cerr << "numerical conversion failure on '" << s << "' "; std::cerr << "(typeid: " << typeid(U).name() << ")" << std::endl; abort(); } } } #endif