#ifndef GENERS_TUPLEIO_HH_ #define GENERS_TUPLEIO_HH_ #include "geners/CPP11_config.hh" #ifdef CPP11_STD_AVAILABLE #include #include #include "geners/GenericIO.hh" #define gs_specialize_template_help_tuple(qualifyer, name, version) /**/ \ template \ struct ClassIdSpecialization > \ {inline static ClassId classId(const bool pt=false) \ {return ClassId(tuple_class_name< name >(#name), version, pt);}}; #define gs_specialize_template_id_tuple(name, version) /**/ \ namespace gs { \ gs_specialize_template_help_tuple(GENERS_EMPTY_TYPE_QUALIFYER_, name, version)\ gs_specialize_template_help_tuple(const, name, version) \ gs_specialize_template_help_tuple(volatile, name, version) \ gs_specialize_template_help_tuple(const volatile, name, version) \ } namespace gs { template Item notImplementedItemCreator(); template struct IOIsTuple > { enum {value = 1}; }; namespace Private { template struct TupleClassIdCycler { inline static void collectClassIds(std::string& os) { TupleClassIdCycler::collectClassIds(os); if (N > 1) os += ','; os += ClassIdSpecialization::type>::classId().id(); } inline static bool dumpClassIds(std::ostream& os) { return TupleClassIdCycler::dumpClassIds(os) && ClassIdSpecialization::type>::classId().write(os); } inline static void fillClassIdVector(std::vector* vec) { TupleClassIdCycler::fillClassIdVector(vec); vec->push_back(ClassIdSpecialization< typename std::tuple_element::type>::classId()); } }; template struct TupleClassIdCycler { inline static void collectClassIds(std::string&) {} inline static bool dumpClassIds(std::ostream&) {return true;} inline static void fillClassIdVector(std::vector* vec) { assert(vec); vec->clear(); } }; template struct TupleIOCycler { template inline static bool write(const Tuple& s, Stream& os, State* st, const bool processClassId) { return TupleIOCycler::write( s, os, st, processClassId) && process_const_item( std::get(s), os, st, processClassId); } template inline static bool read(Tuple* s, Stream& os, StateVec& st, const bool processClassId) { return TupleIOCycler::read( s, os, st, processClassId) && process_item( std::get(*s), os, &st[N-1], processClassId); } inline static void clearPointers(Tuple* s) { TupleIOCycler::clearPointers(s); clearIfPointer(std::get(*s)); } }; template struct TupleIOCycler { template inline static bool write(const Tuple&, Stream&, State*, bool) {return true;} template inline static bool read(Tuple*, Stream&, StateVec&, bool) {return true;} inline static void clearPointers(Tuple*) {} }; inline std::vector make_default_tuple_columns( const unsigned long N) { std::vector names_; names_.reserve(N); for (unsigned long i=0; i std::string tuple_class_name(const char* templateName) { assert(templateName); std::string os(templateName); if (std::tuple_size::value) { os += '<'; Private::TupleClassIdCycler< T, std::tuple_size::value>::collectClassIds(os); os += '>'; } return os; } template const std::vector& default_tuple_columns() { static const std::vector names_( Private::make_default_tuple_columns(N)); return names_; } } gs_specialize_template_id_tuple(std::tuple, 0) namespace gs { template struct GenericWriter::ISTUPLE> > { inline static bool process(const T& s, Stream& os, State* st, const bool processClassId) { static const ClassId current(ClassId::makeId()); return (processClassId ? current.write(os) : true) && Private::TupleIOCycler::value>::write( s, os, st, false); } }; template struct GenericReader::ISTUPLE> > { inline static bool readIntoPtr(T*& ptr, Stream& str, State* s, const bool processClassId) { std::unique_ptr myptr; if (ptr == 0) { myptr = std::unique_ptr(new T()); Private::TupleIOCycler< T, std::tuple_size::value>::clearPointers(myptr.get()); } std::vector > itemIds; if (processClassId) { static const ClassId current(ClassId::makeId()); ClassId id(str, 1); current.ensureSameName(id); id.templateParameters(&itemIds); assert(itemIds.size() == std::tuple_size::value); } else { assert(!s->empty()); s->back().templateParameters(&itemIds); if (itemIds.size() != std::tuple_size::value) { std::string err("In gs::GenericReader::readIntoPtr: " "bad class id for std::tuple on the " "class id stack: "); err += s->back().id(); throw IOInvalidData(err); } } const bool status = Private::TupleIOCycler< T, std::tuple_size::value>::read( ptr ? ptr : myptr.get(), str, itemIds, false); if (status && ptr == 0) ptr = myptr.release(); return status; } inline static bool process(T& s, Stream& os, State* st, const bool processClassId) { T* ps = &s; return readIntoPtr(ps, os, st, processClassId); } }; } #endif // CPP11_STD_AVAILABLE #endif // GENERS_TUPLEIO_HH_