]> git.tdb.fi Git - libs/datafile.git/commitdiff
Add a utility for registering types for loading
authorMikko Rasa <tdb@tdb.fi>
Wed, 12 Jun 2019 10:13:22 +0000 (13:13 +0300)
committerMikko Rasa <tdb@tdb.fi>
Wed, 12 Jun 2019 17:05:50 +0000 (20:05 +0300)
Somewhat ironically Collection can't use this because it has much more
complex requirements.

source/loadabletyperegistry.h [new file with mode: 0644]

diff --git a/source/loadabletyperegistry.h b/source/loadabletyperegistry.h
new file mode 100644 (file)
index 0000000..ace98cb
--- /dev/null
@@ -0,0 +1,83 @@
+#ifndef MSP_DATAFILE_LOADABLETYPEREGISTRY_H_
+#define MSP_DATAFILE_LOADABLETYPEREGISTRY_H_
+
+#include <map>
+#include <string>
+#include <vector>
+#include <msp/core/maputils.h>
+#include <msp/core/noncopyable.h>
+
+namespace Msp {
+namespace DataFile {
+
+/**
+Associates types with keywords for adding to a Loader.  The target Loader class
+must be given as a template parameter, as well as a helper template struct to
+handle the actual adding of keywords.
+*/
+template<typename L, template<typename> class A>
+class LoadableTypeRegistry: public NonCopyable
+{
+private:
+       class TypeBase
+       {
+       protected:
+               std::string keyword;
+
+               TypeBase(const std::string &kw): keyword(kw) { }
+       public:
+               virtual ~TypeBase() { }
+
+               virtual void add(L &) const = 0;
+       };
+
+       template<typename T>
+       class RegisteredType: public TypeBase
+       {
+       public:
+               RegisteredType(const std::string &kw): TypeBase(kw) { }
+
+               virtual void add(L &ldr) const { A<T>::add(ldr, this->keyword); }
+       };
+
+       typedef std::map<std::string, TypeBase *> TypeMap;
+
+       TypeMap types;
+
+public:
+       ~LoadableTypeRegistry();
+
+       template<typename T>
+       void register_type(const std::string &);
+
+       void add_all(L &) const;
+};
+
+template<typename L, template<typename> class A>
+LoadableTypeRegistry<L, A>::~LoadableTypeRegistry()
+{
+       for(typename TypeMap::iterator i=types.begin(); i!=types.end(); ++i)
+               delete i->second;
+}
+
+template<typename L, template<typename> class A>
+template<typename T>
+void LoadableTypeRegistry<L, A>::register_type(const std::string &kw)
+{
+       if(types.count(kw))
+               throw key_error(kw);
+
+       types[kw] = new RegisteredType<T>(kw);
+}
+
+template<typename L, template<typename> class A>
+void LoadableTypeRegistry<L, A>::add_all(L &ldr) const
+{
+       for(typename TypeMap::const_iterator i=types.begin(); i!=types.end(); ++i)
+               i->second->add(ldr);
+}
+
+} // namespace DataFile
+} // namespace Msp
+
+#endif