#ifndef __JSUPPORT__JMETA__ #define __JSUPPORT__JMETA__ #include #include #include #include "RVersion.h" #include "TFile.h" #include "TNamed.h" #include "TString.h" #include "JLang/JType.hh" #include "JLang/JException.hh" #include "JLang/JEquation.hh" #include "JLang/JEquationParameters.hh" #include "JLang/Jpp.hh" #include "JLang/JManip.hh" #include "JROOT/JRootFileReader.hh" #include "JSystem/JUTSName.hh" #include "Jeep/JComment.hh" #include "Jeep/JeepToolkit.hh" /** * \file * * ROOT I/O of application specific meta data. * \author mdejong */ namespace JSUPPORT {} namespace JPP { using namespace JSUPPORT; } namespace JSUPPORT { using JLANG::JType; using JLANG::JException; using JLANG::JEquationParameters; using JEEP::JComment_t; /** * ROOT name for meta data. */ static const char* const META_NAME = "JMeta"; /** * ROOT sub-directory for meta data. */ static const char* const META_DIRECTORY = "META"; /** * Definition of meta data parameters. */ static const char* const application_t = "application"; //!< application name static const char* const SVNrelease_t = "SVN"; //!< SVN release static const char* const GITrelease_t = "GIT"; //!< GIT release static const char* const ROOTrelease_t = "ROOT"; //!< ROOT release static const char* const namespace_t = "namespace"; //!< name space static const char* const command_t = "command"; //!< Linux command static const char* const system_t = "system"; //!< system information /** * Auxiliary class for ROOT I/O of application specific meta data. */ struct JMeta : public std::map { /** * Default constructor. */ JMeta() {} /** * Constructor. * * \param argc number of command line arguments * \param argv array of command line arguments */ JMeta(const int argc, const char* const argv[]) { using namespace std; using namespace JPP; if (argc > 0) { (*this)[application_t] = getFilename(argv[0]); (*this)[GITrelease_t] = getGITVersion(); (*this)[ROOTrelease_t] = ROOT_RELEASE; (*this)[namespace_t] = getNamespace(); (*this)[command_t] = MAKE_STRING(getPath(PATH, argv[0]) << '/' << argv[0]); for (int i = 1; i != argc; ++i) { if (get_number_of_tokens(argv[i]) == 1) (*this)[command_t] += MAKE_STRING(' ' << argv[i]); else (*this)[command_t] += MAKE_STRING(' ' << "\\\"" << argv[i] << "\\\""); } const JUTSName buffer; (*this)[system_t] = MAKE_STRING("" << buffer.sysname << ' ' << buffer.nodename << ' ' << buffer.release << ' ' << buffer.version << ' ' << buffer.machine); } } /** * Type conversion operator. * * \return comment */ operator JComment_t() const { JComment_t comment; for (const_iterator i = this->begin(); i != this->end(); ++i) { comment.push_back(i->first + ' ' + i->second); } return comment; } /** * Copy meta data. * * \param file_name name of input file * \param out output file */ static void copy(const char* const file_name, TFile& out); /** * Get equation parameters. * * \return equation parameters */ static inline const JEquationParameters& getEquationParameters() { static const JEquationParameters parameters("=", "\n", "", ""); return parameters; } /** * Extract meta data. * * \param buffer meta data * \return meta data */ static JMeta valueOf(const std::string& buffer) { using namespace std; using namespace JPP; JMeta meta; istringstream is(buffer); is >> setequation(JMeta::getEquationParameters()); for (JEquation equation; is >> equation; ) { meta[equation.getKey()] = equation.getValue(); } return meta; } /** * Convert meta data to string. * * \return string */ std::string toString() const { using namespace std; using namespace JPP; ostringstream os; os << setequation(JMeta::getEquationParameters()); for (JMeta::const_iterator i = this->begin(); i != this->end(); ++i) { os << JEquation::make_equation(i->first, i->second); } return os.str(); } /** * Write meta data to output. * * \param out output stream * \param meta meta data * \return output stream */ friend inline std::ostream& operator<<(std::ostream& out, const JMeta& meta) { using namespace std; const_iterator p = meta.find(application_t); if (p != meta.end()) { for (const_iterator i = meta.begin(); i != meta.end(); ++i) { if (i != p) { out << p->second << ' ' << i->second << endl; } } } return out; } }; /** * Get ROOT name of given data type. * * \param type JMeta type * \return name of object to be read */ inline const char* getName(const JType& type) { return META_NAME; } /** * Get number of cycles of named objects with same title as given key. * * \param file pointer to file * \param key ROOT key (including possible directory) * \return number of cycles */ inline int getNumberOfCycles(TFile* file, const TString key) { using namespace std; int counter = 0; if (file != NULL) { TNamed* __p = NULL; file->GetObject(key, __p); if (__p != NULL) { ++counter; const TString title = __p->GetTitle(); string buffer(key); const string::size_type pos = buffer.find(';'); if (pos != string::npos) { int cycle = -1; istringstream(buffer.substr(pos + 1)) >> cycle; buffer = buffer.substr(0, pos); for (int i = 1; i < cycle; ++i) { file->GetObject(MAKE_CSTRING(buffer << ';' << i), __p); if (__p != NULL && __p->GetTitle() == title) { ++counter; } } } } } return counter; } /** * Read object from ROOT file. * * \param file pointer to file * \param key key of object to be read * \param ps pointer to object */ inline void getObject(TFile* file, const TString& key, JMeta*& ps) { using namespace std; using namespace JPP; if (ps != NULL) { delete ps; ps = NULL; } if (file != NULL) { const int number_of_cycles = getNumberOfCycles(file, MAKE_CSTRING(META_DIRECTORY << '/' << key)); if (number_of_cycles != 0) { TNamed* __p = NULL; file->GetObject(MAKE_CSTRING(META_DIRECTORY << '/' << key), __p); ps = new JMeta(); (*ps)[application_t] = __p->GetTitle(); file->GetObject(MAKE_CSTRING(META_DIRECTORY << '/' << (*ps)[application_t] << ';' << number_of_cycles), __p); if (__p != NULL) { *ps = JMeta::valueOf(__p->GetTitle()); } } } } /** * Write meta data as ROOT TNamed object. * * \param dir directory * \param key ROOT key * \param buffer user data * \return true if OK; else false */ inline bool putMeta(TDirectory& dir, const std::string key, const std::string buffer) { static TNamed object; if (dir.GetListOfKeys()->FindObject(META_DIRECTORY) == NULL) { dir.mkdir(META_DIRECTORY); } TDirectory* p = dir.GetDirectory(META_DIRECTORY); object.SetName (key.c_str()); // ROOT key object.SetTitle(buffer.c_str()); // user data return (p->WriteTObject(&object) > 0); } /** * Write meta data to ROOT directory. * * \param dir directory * \param meta meta data * \return true if OK; else false */ inline bool putObject(TDirectory& dir, const JMeta& meta) { JMeta::const_iterator p = meta.find(application_t); if (p != meta.end()) { if (putMeta(dir, getName(JType()), p->second)) { return putMeta(dir, p->second, meta.toString()); } } return false; } /** * Write meta data to ROOT directory. * * \param dir pointer to directory * \param meta meta data * \return true if OK; else false */ inline bool putObject(TDirectory* dir, const JMeta& meta) { if (dir != NULL) return putObject(*dir, meta); else return false; } /** * Write meta data to ROOT file. * * \param file ROOT file * \param meta meta data * \return ROOT file */ inline TFile& operator<<(TFile& file, const JMeta& meta) { putObject(file, meta); return file; } /** * Copy meta data. * * \param file_name name of input file * \param out output file */ void JMeta::copy(const char* const file_name, TFile& out) { using namespace JPP; JRootFileReader in(file_name); while (in.hasNext()) { const JMeta* p = in.next(); putObject(out, *p); } } /** * Type definition of old meta data. */ struct JMetaOld_t : public JMeta {}; /** * Get ROOT name of given data type. * * \param type JMetaOld_t type * \return name of object to be read */ inline const char* getName(const JType& type) { return META_NAME; } /** * Read object from ROOT file. * * \param file pointer to file * \param key key of object to be read * \param ps pointer to object */ inline void getObject(TFile* file, const TString& key, JMetaOld_t*& ps) { enum JParameter_t { JApplication_t = 0, //!< application name JSVNRelease_t, //!< SVN release JROOTRelease_t, //!< ROOT release JNamespace_t, //!< name space JCommand_t, //!< Linux command JSystem_t, //!< system information number_of_items //!< number of items }; const char* buffer[number_of_items] = { application_t, SVNrelease_t, ROOTrelease_t, namespace_t, command_t, system_t }; if (ps != NULL) { delete ps; ps = NULL; } if (file != NULL) { const int number_of_cycles = getNumberOfCycles(file, key); if (number_of_cycles != 0) { TNamed* __p = NULL; file->GetObject(key, __p); ps = new JMetaOld_t(); (*ps)[application_t] = __p->GetTitle(); for (int i = 1; i != number_of_items; ++i) { file->GetObject(MAKE_CSTRING((*ps)[application_t] << ';' << ((number_of_cycles - 1) * (number_of_items - 1) + i)), __p); if (__p != NULL) (*ps)[buffer[i]] = __p->GetTitle(); else break; } } } } /** * Write old meta data to ROOT directory in new format. * * \param dir directory * \param meta meta data * \return true if OK; else false */ inline bool putObject(TDirectory& dir, const JMetaOld_t& meta) { return putObject(dir, static_cast(meta)); } } #endif