From: Mikko Rasa Date: Tue, 5 Oct 2021 10:55:37 +0000 (+0300) Subject: Add a class for loading dynamically typed objects X-Git-Url: http://git.tdb.fi/?a=commitdiff_plain;h=794461b9f73a20c086f456459e39a98387060c3a;p=libs%2Fdatafile.git Add a class for loading dynamically typed objects --- diff --git a/source/dynamicobjectloader.h b/source/dynamicobjectloader.h new file mode 100644 index 0000000..c83d914 --- /dev/null +++ b/source/dynamicobjectloader.h @@ -0,0 +1,118 @@ +#ifndef MSP_DATAFILE_DYNAMICOBJECTLOADER_H_ +#define MSP_DATAFILE_DYNAMICOBJECTLOADER_H_ + +#include +#include "except.h" +#include "loader.h" + +namespace Msp { +namespace DataFile { + +class Collection; + +/** +Loads a dynamically typed object, with the type specified as a statement. The +T template parameter is the common base class for all possible loaded types. +*/ +template +class DynamicObjectLoader: public Loader +{ +public: + typedef C Collection; + +protected: + template + struct CreateObject + { + void operator()(const std::string &, DynamicObjectLoader &) const; + }; + + typedef Msp::TypeRegistry TypeRegistry; + + Collection *coll; +private: + T *object; + Loader *obj_loader; + + static ActionMap shared_actions; + +protected: + DynamicObjectLoader(Collection *); +public: + ~DynamicObjectLoader() { delete object; delete obj_loader; } + + T *get_object() { T *o = object; object = 0; return o; } +private: + virtual void init_actions(); + + void type(const Symbol &); + + template + typename std::enable_if::value, typename U::Loader *>::type create_object_loader(U &obj) const; + + template + typename std::enable_if::value, typename U::Loader *>::type create_object_loader(U &obj) const; + +protected: + virtual const TypeRegistry &get_type_registry() const = 0; +}; + + +template +Loader::ActionMap DynamicObjectLoader::shared_actions; + +template +DynamicObjectLoader::DynamicObjectLoader(Collection *c): + coll(c), + object(0), + obj_loader(0) +{ + set_actions(shared_actions); +} + +template +void DynamicObjectLoader::init_actions() +{ + add("type", &DynamicObjectLoader::type); +} + +template +void DynamicObjectLoader::type(const Symbol &t) +{ + if(obj_loader) + throw std::logic_error("duplicate type statement"); + + get_type_registry().invoke(t.name, *this); +} + +template +template +typename std::enable_if::value, typename U::Loader *>::type DynamicObjectLoader::create_object_loader(U &obj) const +{ + if(!coll) + throw no_collection(typeid(U)); + return new typename U::Loader(obj, *coll); +} + +template +template +typename std::enable_if::value, typename U::Loader *>::type DynamicObjectLoader::create_object_loader(U &obj) const +{ + return new typename U::Loader(obj); +} + + +template +template +void DynamicObjectLoader::CreateObject::operator()(const std::string &, DynamicObjectLoader &ldr) const +{ + U *obj = new U; + ldr.object = obj; + ldr.obj_loader = ldr.create_object_loader(*obj); + ldr.add_auxiliary_loader(*ldr.obj_loader); +} + +} // namespace DataFile +} // namespace Msp + +#endif