Back to home page

Project CMSSW displayed by LXR

 
 

    


File indexing completed on 2024-04-06 11:56:17

0001 //=========================================================================
0002 // AbsReader.hh
0003 //
0004 // Template implementation of a factory pattern for reading objects from
0005 // C++ streams. Derive a reader for your concrete inheritance hierarchy
0006 // from the "DefaultReader" template (as illustrated by the examples
0007 // provided with the package). Wrap your reader using the "StaticReader"
0008 // template when the actual reading is performed to ensure that the reader
0009 // factory is unique.
0010 //
0011 // The classes which can be read must implement the static "read" function
0012 // which creates objects on the heap. The signature of this function is
0013 //
0014 // static ClassName* read(const ClassId& id, std::istream& is);
0015 //
0016 // In this function, the class id argument can be used to implement object
0017 // versioning. The "read" method must always succeed. If it is unable to
0018 // build the object, it must throw an exception which inherits from
0019 // std::exception.
0020 //
0021 // I. Volobouev
0022 // September 2010
0023 //=========================================================================
0024 
0025 #ifndef GENERS_ABSREADER_HH_
0026 #define GENERS_ABSREADER_HH_
0027 
0028 #include "Alignment/Geners/interface/IOException.hh"
0029 #include <map>
0030 #include <sstream>
0031 #include <string>
0032 
0033 #include "Alignment/Geners/interface/ClassId.hh"
0034 
0035 namespace gs {
0036   template <class Base>
0037   struct AbsReader {
0038     virtual ~AbsReader() {}
0039 
0040     virtual Base *read(const ClassId &id, std::istream &in) const = 0;
0041   };
0042 
0043   template <class Base, class Derived>
0044   struct ConcreteReader : public AbsReader<Base> {
0045     ~ConcreteReader() override {}
0046 
0047     inline Derived *read(const ClassId &id, std::istream &in) const override {
0048       // Assume that Derived::read(id, in) returns a new object
0049       // of type "Derived" allocated on the heap
0050       return Derived::read(id, in);
0051     }
0052   };
0053 
0054   template <class Base>
0055   class DefaultReader : public std::map<std::string, AbsReader<Base> *> {
0056   public:
0057     typedef Base value_type;
0058 
0059     inline DefaultReader() : std::map<std::string, AbsReader<Base> *>() {}
0060 
0061     virtual ~DefaultReader() {
0062       for (typename std::map<std::string, AbsReader<Base> *>::iterator it = this->begin(); it != this->end(); ++it)
0063         delete it->second;
0064     }
0065 
0066     inline Base *read(const ClassId &id, std::istream &in) const {
0067       typename std::map<std::string, AbsReader<Base> *>::const_iterator it = this->find(id.name());
0068       if (it == this->end()) {
0069         std::ostringstream os;
0070         os << "In gs::DefaultReader::read: class \"" << id.name() << "\" is not mapped to a concrete reader";
0071         throw gs::IOInvalidArgument(os.str());
0072       }
0073       return it->second->read(id, in);
0074     }
0075 
0076     DefaultReader(const DefaultReader &) = delete;
0077     DefaultReader &operator=(const DefaultReader &) = delete;
0078   };
0079 
0080   // A trivial implementation of the Meyers singleton for use with reader
0081   // factories. Naturally, this assumes that all factories are independent
0082   // from each other (otherwise we are getting into trouble with undefined
0083   // singleton destruction order). Also, this particular code is not
0084   // thread-safe (but should become thread-safe in C++11 if I understand
0085   // static local initialization guarantees correctly).
0086   //
0087   // Assume that "Reader" is derived from "DefaultReader" and that it
0088   // publishes its base class as "Base".
0089   //
0090   template <class Reader>
0091   class StaticReader {
0092   public:
0093     typedef typename Reader::Base::value_type InheritanceBase;
0094 
0095     static const Reader &instance() {
0096       static const Reader obj;
0097       return obj;
0098     }
0099 
0100     template <class Derived>
0101     static void registerClass() {
0102       Reader &rd = const_cast<Reader &>(instance());
0103       const ClassId &id(ClassId::makeId<Derived>());
0104       delete rd[id.name()];
0105       rd[id.name()] = new ConcreteReader<InheritanceBase, Derived>();
0106     }
0107 
0108     // Disable the constructor
0109     StaticReader() = delete;
0110   };
0111 }  // namespace gs
0112 
0113 #endif  // GENERS_ABSREADER_HH_