diff options
Diffstat (limited to 'libodb/odb/polymorphic-info.hxx')
-rw-r--r-- | libodb/odb/polymorphic-info.hxx | 188 |
1 files changed, 188 insertions, 0 deletions
diff --git a/libodb/odb/polymorphic-info.hxx b/libodb/odb/polymorphic-info.hxx new file mode 100644 index 0000000..0f410d5 --- /dev/null +++ b/libodb/odb/polymorphic-info.hxx @@ -0,0 +1,188 @@ +// file : odb/polymorphic-info.hxx +// license : GNU GPL v2; see accompanying LICENSE file + +#ifndef ODB_POLYMORPHIC_INFO_HXX +#define ODB_POLYMORPHIC_INFO_HXX + +#include <odb/pre.hxx> + +#include <cstddef> // std::size_t +#include <typeinfo> + +#include <odb/forward.hxx> // database, connection +#include <odb/schema-version.hxx> +#include <odb/traits.hxx> + +namespace odb +{ + template <typename R> + struct polymorphic_abstract_info + { + typedef void (*section_load) (odb::connection&, R&, bool top); + typedef void (*section_update) (odb::connection&, const R&); + + struct section_functions + { + section_load load; + section_update update; + }; + + struct section_list + { + std::size_t count; + const section_functions* functions; + }; + + public: + polymorphic_abstract_info (const std::type_info& t, + const polymorphic_abstract_info* b, + const section_list* s) + : type (t), base (b), sections (s) {} + + bool + derived (const polymorphic_abstract_info& b) const + { + for (const polymorphic_abstract_info* p (base); p != 0; p = p->base) + if (&b == p) + return true; + + return false; + } + + // Find the "most overridden" section functions. + // + section_load + find_section_load (std::size_t index) const + { + for (const polymorphic_abstract_info* b (this); b != 0; b = b->base) + if (b->sections != 0 && + index < b->sections->count && + b->sections->functions[index].load != 0) + return b->sections->functions[index].load; + + return 0; + } + + section_update + find_section_update (std::size_t index) const + { + for (const polymorphic_abstract_info* b (this); b != 0; b = b->base) + if (b->sections != 0 && + index < b->sections->count && + b->sections->functions[index].update != 0) + return b->sections->functions[index].update; + + return 0; + } + + bool + final_section_update (const polymorphic_abstract_info& i, + std::size_t index) const + { + return i.sections != 0 && + index < i.sections->count && + i.sections->functions[index].update != 0 && + i.sections->functions[index].update == find_section_update (index); + } + + public: + const std::type_info& type; + const polymorphic_abstract_info* base; + + // Sections. + // + // There could be "concrete" (i.e., not overridden) section in an + // abstract class. Which means the section table has to be in + // abstract_info. + // + const section_list* sections; + }; + + template <typename R> + struct polymorphic_concrete_info: polymorphic_abstract_info<R> + { + // Have to use access::object_traits directly because of VC10. + // + typedef R root_type; + typedef access::object_traits<root_type> root_traits; + typedef typename root_traits::id_type id_type; + typedef typename root_traits::pointer_type pointer_type; + typedef typename root_traits::discriminator_type discriminator_type; + + typedef typename polymorphic_abstract_info<R>::section_list section_list; + + enum call_type + { + call_callback, // arg points to callback event. + call_persist, // arg is not used. + call_update, // arg is not used. + call_find, // arg points to object id. + call_reload, // arg is not used. + call_load, // arg points to depth. + call_erase // arg points to object id. + }; + + typedef pointer_type (*create_function) (); + typedef bool (*dispatch_function) ( + call_type, odb::database&, const root_type*, const void* arg); + typedef void (*delayed_loader_function) ( + odb::database&, + const id_type&, + root_type&, + const schema_version_migration*); + + public: + polymorphic_concrete_info (const std::type_info& t, + const polymorphic_abstract_info<R>* b, + const section_list* s, + const discriminator_type& d, + create_function cf, + dispatch_function df, + delayed_loader_function dlf) + : polymorphic_abstract_info<R> (t, b, s), + discriminator (d), + create (cf), dispatch (df), delayed_loader (dlf) + { + } + + public: + discriminator_type discriminator; + create_function create; + dispatch_function dispatch; + delayed_loader_function delayed_loader; + }; + + // Register concrete type T in the root's map. + // + template <typename T, database_id DB> + struct polymorphic_entry + { + typedef T object_type; + typedef object_traits_impl<object_type, DB> object_traits; + typedef typename object_traits::root_type root_type; + + polymorphic_entry (); + ~polymorphic_entry (); + }; + + // Helper functions that either return the concrete info or NULL + // depending on what kind of info we pass (used in query support). + // + template <typename R> + inline const polymorphic_concrete_info<R>* + polymorphic_info (const polymorphic_concrete_info<R>& i) + { + return &i; + } + + template <typename R> + inline const polymorphic_concrete_info<R>* + polymorphic_info (const polymorphic_abstract_info<R>&) + { + return 0; + } +} + +#include <odb/post.hxx> + +#endif // ODB_POLYMORPHIC_INFO_HXX |