1 #ifndef MSP_DATAFILE_DYNAMICOBJECTLOADER_H_
2 #define MSP_DATAFILE_DYNAMICOBJECTLOADER_H_
4 #include <msp/core/typeregistry.h>
5 #include "collection.h"
15 Loads a dynamically typed object, with the type specified as a statement. The
16 T template parameter is the common base class for all possible loaded types.
18 template<typename T, typename C = Collection>
19 class DynamicObjectLoader: public Loader
28 void operator()(const std::string &, DynamicObjectLoader &) const;
31 typedef Msp::TypeRegistry<CreateObject, DynamicObjectLoader &> TypeRegistry;
33 Collection *coll = nullptr;
36 Loader *obj_loader = nullptr;
37 void (*store_func)(Collection &, const std::string &, T *) = nullptr;
39 static ActionMap shared_actions;
42 DynamicObjectLoader(Collection *);
44 ~DynamicObjectLoader() { delete object; delete obj_loader; }
47 void init_actions() override;
50 T *get_object() { T *o = object; object = 0; return o; }
51 T *store_object(Collection &, const std::string &);
54 virtual void type(const Symbol &);
58 typename std::enable_if<NeedsCollection<typename U::Loader>::value, typename U::Loader *>::type create_object_loader(U &obj) const;
61 typename std::enable_if<!NeedsCollection<typename U::Loader>::value, typename U::Loader *>::type create_object_loader(U &obj) const;
64 virtual const TypeRegistry &get_type_registry() const = 0;
68 template<typename T, typename C>
69 Loader::ActionMap DynamicObjectLoader<T, C>::shared_actions;
71 template<typename T, typename C>
72 DynamicObjectLoader<T, C>::DynamicObjectLoader(Collection *c):
75 set_actions(shared_actions);
78 template<typename T, typename C>
79 void DynamicObjectLoader<T, C>::init_actions()
81 add("type", &DynamicObjectLoader::type);
84 template<typename T, typename C>
85 T *DynamicObjectLoader<T, C>::store_object(Collection &c, const std::string &name)
88 throw std::logic_error("no store function");
91 store_func(c, name, object);
96 template<typename T, typename C>
97 void DynamicObjectLoader<T, C>::type(const Symbol &t)
100 throw std::logic_error("duplicate type statement");
102 get_type_registry().invoke(t.name, *this);
105 template<typename T, typename C>
107 typename std::enable_if<NeedsCollection<typename U::Loader>::value, typename U::Loader *>::type DynamicObjectLoader<T, C>::create_object_loader(U &obj) const
110 throw no_collection(typeid(U));
111 return new typename U::Loader(obj, *coll);
114 template<typename T, typename C>
116 typename std::enable_if<!NeedsCollection<typename U::Loader>::value, typename U::Loader *>::type DynamicObjectLoader<T, C>::create_object_loader(U &obj) const
118 return new typename U::Loader(obj);
122 template<typename T, typename C>
124 void DynamicObjectLoader<T, C>::CreateObject<U>::operator()(const std::string &, DynamicObjectLoader &ldr) const
128 ldr.obj_loader = ldr.create_object_loader<U>(*obj);
129 ldr.add_auxiliary_loader(*ldr.obj_loader);
130 ldr.store_func = [](Collection &c, const std::string &n, T *o){ c.add(n, static_cast<U *>(o)); };
133 } // namespace DataFile