#ifndef __JROOT__JROOTSTREAMER__ #define __JROOT__JROOTSTREAMER__ #include #include #include #include #include #include "JLang/JEquation.hh" #include "JLang/JEquationParameters.hh" #include "JLang/JEquationFacet.hh" #include "JLang/JStreamAvailable.hh" #include "JLang/JBool.hh" #include "JLang/JRedirectString.hh" #include "JLang/JRedirectStream.hh" #include "JLang/JStreamState.hh" #include "JROOT/JAbstractStreamer.hh" #include "JROOT/JRootClass.hh" #include "JROOT/JRootDictionary_t.hh" /** * \file * * ASCII I/O of objects with ROOT dictionary. * \author mdejong */ namespace JROOT {} namespace JPP { using namespace JROOT; } namespace JROOT { using JLANG::JEquation; using JLANG::JEquationParameters; using JLANG::JBool; using JLANG::JStreamState; using JLANG::JException; /** * Implementation for ASCII input of objects with ROOT dictionary. * * The method JRootReader::get is compatible with equation formatting, i.e: * *
\[\\]\\[\\]*\
* * In this, the key corresponds to the name of a data member, * which can be recursively parsed via a division character.\n * \n * The method JRootReader::getObject relates to simple formatting, i.e: * *
\[\\]*
* * The default format for input of std::vector\ is * *
\[\\]*
*/ class JRootReader : public std::istream, private JStreamState { public: /** * Constructor. * * \param in input stream * \param parameters equation parameters * \param dictionary dictionary */ JRootReader(std::istream& in, const JEquationParameters& parameters, const JRootDictionary_t& dictionary) : std::istream(in.rdbuf()), JStreamState(in, static_cast(*this)), dictionary(dictionary) { imbue(std::locale(in.getloc(), new JLANG::JEquationFacet(parameters))); } /** * Get dictionary. * * \return dictionary */ const JRootDictionary_t& getDictionary() const { return dictionary; } /** * Read object according equation format. * * \param object object * \return this ROOT reader */ template JRootReader& get(T& object) { return this->get(JRootReadableClass(object)); } /** * Read ROOT class according equation format. * * \param cls ROOT class * \return this ROOT reader */ JRootReader& get(const JRootReadableClass& cls) { using namespace std; using namespace JPP; if (cls.is_valid()) { const JEquationFacet& facet = use_facet(this->getloc()); for (JEquation equation; *this >> equation; ) { const JRootReadableClass abc = cls.find(equation.getKey().c_str()); bool status = abc.is_valid(); if (status) { JRedirectString redirect(*this, equation.getValue()); if (facet.isDivision (equation.getSeparator())) this->get(abc); else if (facet.isSeparator(equation.getSeparator())) this->getObject(abc); else status = false; status &= (!this->fail() || this->eof()); } if (!status) { THROW(JException, "Error parsing: " << equation); } } } return *this; } /** * Read object. * * \param object object * \return this ROOT reader */ template JRootReader& getObject(T& object) { return this->getObject(object, JBool::has_istream>()); } /** * Read ROOT class. * * \param cls ROOT class * \return this ROOT reader */ JRootReader& getObject(const JRootReadableClass& cls) { if (cls.is_valid()) { JRootDictionary_t::const_iterator i = this->getDictionary().find(cls.getTypename()); if (i != this->getDictionary().end()) { i->second->getObject(*this, cls.getAddress()); } else if (cls.getClass() != NULL) { if (cls.getClass()->GetListOfBases() != NULL) { std::unique_ptr i(cls.getClass()->GetListOfBases()->MakeIterator()); for (const TBaseClass* p; (p = (const TBaseClass*) i->Next()) != NULL && (bool) (*this); ) { this->getObject(cls.get(*p)); } } if (cls.getClass()->GetListOfDataMembers() != NULL) { std::unique_ptr i(cls.getClass()->GetListOfDataMembers()->MakeIterator()); for (const TDataMember* p; (p = (const TDataMember*) i->Next()) != NULL && (bool) (*this); ) { this->getObject(cls.get(*p)); } } } } return *this; } /** * Read ROOT class. * * \param cls ROOT class * \return this ROOT reader */ JRootReader& getObject(JRootReadableClass& cls) { return getObject(const_cast(cls)); } private: /** * Read object. * * \param object object * \param option true * \return this ROOT reader */ template JRootReader& getObject(T& object, const JBool& option) { *this >> object; return *this; } /** * Read object. * * \param object object * \param option false * \return this ROOT reader */ template JRootReader& getObject(T& object, const JBool& option) { return this->getObject(JRootReadableClass(object)); } /** * Read object. * * \param object object * \param option false * \return this ROOT reader */ template JRootReader& getObject(std::vector& object, const JBool& option) { int n = 0; this->getObject(n); for (JElement_t element; n != 0 && this->getObject(element); --n) { object.push_back(element); } return *this; } const JRootDictionary_t& dictionary; }; /** * Implementation for ASCII output of objects with ROOT dictionary. * * The method JRootWriter::put is compatible with equation formatting, i.e: * *
\[\\]\\[\\]*\
* * In this, the key corresponds to the name of a data member * which can be recursively parsed via a division character.\n * \n * The method JRootWriter::putObject relates to simple formatting, i.e: * *
\[\\]*
* * The default format for output of std::vector\ is * *
\[\\]*
*/ class JRootWriter : public std::ostream, private JStreamState { public: /** * Constructor. * * \param out output stream * \param parameters equation parameters * \param dictionary dictionary */ JRootWriter(std::ostream& out, const JEquationParameters& parameters, const JRootDictionary_t& dictionary) : std::ostream(out.rdbuf()), JStreamState(out, static_cast(*this)), dictionary(dictionary) { imbue(std::locale(out.getloc(), new JLANG::JEquationFacet(parameters))); flags (out.flags()); width (out.width()); precision(out.precision()); } /** * Get dictictionary. * * \return dictionary */ const JRootDictionary_t& getDictionary() const { return dictionary; } /** * Write object according equation format. * * \param object object * \return this ROOT writer */ template JRootWriter& put(const T& object) { return this->put(JRootWritableClass(object)); } /** * Write given key and value according equation format. * * \param key key * \param value value * \return this ROOT writer */ template JRootWriter& put(const std::string& key, const T& value) { using namespace std; using namespace JPP; ostringstream os; { JRedirectStream redirect(*this, os); this->putObject(value); } return this->put(JEquation(key, os.str())); } /** * Write ROOT class according equation format. * * \param cls ROOT class * \return this ROOT writer */ JRootWriter& put(const JRootWritableClass& cls) { return this->put("", cls, false); } /** * Write ROOT class according equation format. * * \param cls ROOT class * \return this ROOT writer */ JRootWriter& put(JRootWritableClass& cls) { return this->put(const_cast(cls)); } /** * Write ROOT class according equation format. * * \param prefix prefix * \param cls ROOT class * \param eol end-of-line * \return object output */ JRootWriter& put(const std::string& prefix, const JRootWritableClass& cls, bool eol) { using namespace std; using namespace JPP; if (cls.is_valid()) { const JEquationFacet& facet = use_facet(this->getloc()); JRootDictionary_t::const_iterator i = this->getDictionary().find(cls.getTypename()); if (i != this->getDictionary().end()) { i->second->put(*this, prefix, cls.getAddress()); } else if (eol) { ostringstream os; { JRedirectStream redirect(*this, os); this->putObject(cls); } this->put(JEquation(prefix, os.str())); } else if (cls.getClass() != NULL) { if (cls.getClass()->GetListOfBases() != NULL) { std::unique_ptr i(cls.getClass()->GetListOfBases()->MakeIterator()); for (const TBaseClass* p; (p = (const TBaseClass*) i->Next()) != NULL; ) { this->put(prefix, cls.get(*p), false); } } if (cls.getClass()->GetListOfDataMembers() != NULL) { std::unique_ptr i(cls.getClass()->GetListOfDataMembers()->MakeIterator()); for (const TDataMember* p; (p = (const TDataMember*) i->Next()) != NULL; ) { if (!JRootClass::is_static(*p)) { this->put(facet.getPrefix(prefix,p->GetName()), cls.get(*p), false); } } } } } return *this; } /** * Write equation. * * \param equation equation * \return this ROOT writer */ virtual JRootWriter& put(const JEquation& equation) { *this << equation; return *this; } /** * Write object. * * \param object object * \return this ROOT writer */ template JRootWriter& putObject(const T& object) { return this->putObject(object, JBool::has_ostream>()); } /** * Write ROOT class. * * \param cls ROOT class * \return object output */ JRootWriter& putObject(const JRootWritableClass& cls) { using namespace std; if (cls.is_valid()) { JRootDictionary_t::const_iterator i = this->getDictionary().find(cls.getTypename()); if (i != this->getDictionary().end()) { i->second->putObject(*this, cls.getAddress()); } else if (cls.getClass() != NULL) { if (cls.getClass()->GetListOfBases() != NULL) { std::unique_ptr i(cls.getClass()->GetListOfBases()->MakeIterator()); for (const TBaseClass* p; (p = (const TBaseClass*) i->Next()) != NULL; ) { this->putObject(cls.get(*p)); } } if (cls.getClass()->GetListOfDataMembers() != NULL) { std::unique_ptr i(cls.getClass()->GetListOfDataMembers()->MakeIterator()); for (const TDataMember* p; (p = (const TDataMember*) i->Next()) != NULL; ) { if (!JRootClass::is_static(*p)) { this->putObject(cls.get(*p)); } } } } } return *this; } private: /** * Write object. * * \param object object * \param option true * \return this ROOT writer */ template JRootWriter& putObject(const T& object, const JBool& option) { using namespace JPP; *this << white_space; *this << object; return *this; } /** * Write object. * * \param object object * \param option false * \return this ROOT writer */ template JRootWriter& putObject(const T& object, const JBool& option) { return this->putObject(JRootWritableClass(object)); } /** * Write object. * * \param object object * \param option false * \return this ROOT writer */ template JRootWriter& putObject(const std::vector& object, const JBool option) { this->putObject(object.size()); for (typename std::vector::const_iterator i = object.begin(); i != object.end(); ++i) { this->putObject(*i); } return *this; } const JRootDictionary_t& dictionary; }; /** * Auxiliary template class to define default implementation of the ROOT streamer. * * This class transfers the I/O functionality to the JRootReader or JRootWriter class.\n * For a custom implementation of the I/O a given class, this class should be specialised.\n * The class should also be added to the dictionary in use (method JRootDictionary::add). */ template struct JRootStreamer { /** * Read object. * * \param reader ROOT reader * \param object object * \return ROOT reader */ static JRootReader& getObject(JRootReader& reader, T& object) { return reader.getObject(object); } /** * Write object. * * \param writer ROOT writer * \param object object * \return ROOT writer */ static JRootWriter& putObject(JRootWriter& writer, const T& object) { return writer.putObject(object); } /** * Write given key and value according equation format. * * \param writer ROOT writer * \param key key * \param value value * \return ROOT writer */ static JRootWriter& put(JRootWriter& writer, const std::string& key, const T& value) { return writer.put(key, value); } }; /** * JObjectStreamer class. * * This class implements the JROOT::JAstractStreamer interface for the given template class.\n * The I/O functionality is transferred first to the JRootStreamer class and * subsequently -by default- to the JRootReader and JRootWriter class.\n */ template class JObjectStreamer : public JAbstractStreamer { public: /** * Stream input. * * \param in object reader * \param address pointer to object * \return object reader */ virtual JRootReader& getObject(JRootReader& in, void* address) const { return JRootStreamer::getObject(in, * ((T*) address)); } /** * Stream output. * * \param out object writer * \param address pointer to object * \return object writer */ virtual JRootWriter& putObject(JRootWriter& out, const void* address) const { return JRootStreamer::putObject(out, * ((const T*) address)); } /** * Stream output. * * \param out object writer * \param prefix prefix * \param address pointer to object * \return object writer */ virtual JRootWriter& put(JRootWriter& out, const std::string& prefix, const void* address) const { return JRootStreamer::put(out, prefix, * ((const T*) address)); } }; } #endif