diff options
Diffstat (limited to 'odb/odb/common.hxx')
-rw-r--r-- | odb/odb/common.hxx | 468 |
1 files changed, 468 insertions, 0 deletions
diff --git a/odb/odb/common.hxx b/odb/odb/common.hxx new file mode 100644 index 0000000..149def7 --- /dev/null +++ b/odb/odb/common.hxx @@ -0,0 +1,468 @@ +// file : odb/common.hxx +// license : GNU GPL v3; see accompanying LICENSE file + +#ifndef ODB_COMMON_HXX +#define ODB_COMMON_HXX + +#include <string> +#include <vector> +#include <cstddef> // std::size_t +#include <cassert> + +#include <odb/context.hxx> +#include <odb/instance.hxx> + +// Traverse object members recursively by going into bases and +// composite members. +// +struct object_members_base: traversal::class_, virtual context +{ + virtual void + traverse_simple (semantics::data_member&); + + // Traverse object pointer. The second argument is the pointed-to + // class. When overriding this function, you will most likely want + // to call the base in order to traverse the pointer as a simple + // member (simple object id) or as composite (composite object id). + // + virtual void + traverse_pointer (semantics::data_member&, semantics::class_&); + + // If you override this function, you can call the base to traverse + // bases and members. The first argument is the data member and can + // be NULL if we are traversing the root type or a base. The second + // argument is the actual composite type, which is not necessarily + // the same as the member's type. + // + virtual void + traverse_composite (semantics::data_member*, semantics::class_&); + + // More general version of the above function that allows detection + // of wrapped composite value. By default this function calls + // traverse_composite (m, comp) ignoring the wrapper type. Note that + // this function is called for all composite value (wrapped or not). + // If it is not wrapped, the wrapper argument will be NULL. + // + virtual void + traverse_composite_wrapper (semantics::data_member*, + semantics::class_& comp, + semantics::type* wrapper); + + // The second argument is the actual container type in case the + // member type is a wrapper. + // + virtual void + traverse_container (semantics::data_member&, semantics::type&); + + // If you override this function, you can call the base to traverse + // bases and members. + // + virtual void + traverse_object (semantics::class_&); + + // If you override this function, you can call the base to traverse + // members. + // + virtual void + traverse_view (semantics::class_&); + + virtual bool + section_test (data_member_path const&); + +public: + object_members_base (bool traverse_poly_base = false, + object_section* section = 0) + : section_ (section), top_level_ (true), member_ (*this) + { + init (false, false, false, traverse_poly_base); + } + + object_members_base (bool build_flat_prefix, + bool build_table_prefix, + bool build_member_prefix, + bool traverse_poly_base = false, + object_section* section = 0) + : section_ (section), top_level_ (true), member_ (*this) + { + init (build_flat_prefix, + build_table_prefix, + build_member_prefix, + traverse_poly_base); + } + + object_members_base (object_members_base const& x) + : context (), //@@ -Wextra + section_ (x.section_), + top_level_ (true), + member_ (*this) + { + init (x.build_flat_prefix_, + x.build_table_prefix_, + x.build_member_prefix_, + x.traverse_poly_base_); + } + + virtual void + traverse (semantics::class_&); + +protected: + string flat_prefix_; + table_prefix table_prefix_; + string member_prefix_; + + data_member_path member_path_; + data_member_scope member_scope_; + + object_section* section_; + +protected: + semantics::data_member* + id () const + { + assert (!member_path_.empty ()); + return context::id (member_path_); + } + +private: + void + init (bool build_flat_prefix, + bool build_table_prefix, + bool build_member_prefix, + bool traverse_poly_base) + { + build_flat_prefix_ = build_flat_prefix; + build_table_prefix_ = build_table_prefix; + build_member_prefix_ = build_member_prefix; + traverse_poly_base_ = traverse_poly_base; + + *this >> names_ >> member_; + *this >> inherits_ >> *this; + } + +private: + virtual void + traverse_member (semantics::data_member&, semantics::type&); + + struct member: traversal::data_member + { + member (object_members_base& om): om_ (om) {} + + virtual void + traverse (semantics::data_member&); + + public: + object_members_base& om_; + }; + + bool build_flat_prefix_; + bool build_table_prefix_; + bool build_member_prefix_; + + bool traverse_poly_base_; + + bool top_level_; + + member member_; + traversal::names names_; + traversal::inherits inherits_; +}; + +// Traverse object columns recursively by going into composite members +// and bases. +// +struct object_columns_base: traversal::class_, virtual context +{ + // Returning false means that the column has been ignored and the + // first flag should not be changed. + // + virtual bool + traverse_column (semantics::data_member&, + string const& name, + bool first); + + // Traverse object pointer. The second argument is the pointed-to + // class. When overriding this function, you will most likely want + // to call the base in order to traverse the member as a column + // (simple object id) or columns (composite object id). + // + virtual void + traverse_pointer (semantics::data_member&, semantics::class_&); + + virtual void + traverse_points_to (semantics::data_member&, semantics::class_&); + + // If you override this function, you can call the base to traverse + // bases and members. The first argument is the data member and can + // be NULL if we are traversing the root type or a base. The second + // argument is the actual composite type, which is not necessarily + // the same as the member type. + // + virtual void + traverse_composite (semantics::data_member*, semantics::class_&); + + // If you override this function, you can call the base to traverse + // bases and members. + // + virtual void + traverse_object (semantics::class_&); + + // If you override this function, you can call the base to traverse + // members. + // + virtual void + traverse_view (semantics::class_&); + + // Called after the last column, provided at least one column hasn't + // been ignored. + // + virtual void + flush (); + + virtual bool + section_test (data_member_path const&); + + // Start/end traversal callbacks. + // + virtual void + traverse_pre (semantics::nameable&); + + virtual void + traverse_post (semantics::nameable&); + +public: + object_columns_base (bool first = true, + column_prefix const& cp = column_prefix (), + object_section* section = 0) + : column_prefix_ (cp), + section_ (section), + root_ (0), + traverse_poly_base_ (false), + first_ (first), + top_level_ (true), + member_ (*this) + { + init (); + } + + object_columns_base (bool first, + bool traverse_poly_base, + object_section* section = 0) + : section_ (section), + root_ (0), + traverse_poly_base_ (traverse_poly_base), + first_ (first), + top_level_ (true), + member_ (*this) + { + init (); + } + + object_columns_base (object_columns_base const& x) + : context (), //@@ -Wextra + column_prefix_ (x.column_prefix_), + section_ (x.section_), + root_ (0), + traverse_poly_base_ (x.traverse_poly_base_), + first_ (x.first_), + top_level_ (true), + member_ (*this) + { + init (); + } + + virtual void + traverse (semantics::class_&); + + // Traverse a data member with type, which can be a simple or composite + // value type, or an object pointer (with a simple or composite id). + // + virtual void + traverse (semantics::data_member&); + + virtual void + traverse (semantics::data_member& m, column_prefix const& cp) + { + column_prefix op (column_prefix_); + column_prefix_ = cp; + traverse (m); + column_prefix_ = op; + } + + virtual void + traverse (data_member_path& mp) + { + data_member_path op (member_path_); + member_path_ = mp; + traverse (*mp.back (), column_prefix (mp)); + member_path_ = op; + } + + // Should only be used for containers. + // + virtual void + traverse (semantics::data_member&, + semantics::type&, + string const& key_prefix, + string const& default_name, + semantics::class_* top_object = 0); // If not 0, switch top object. + +protected: + string key_prefix_; + string default_name_; + + column_prefix column_prefix_; + + data_member_path member_path_; + data_member_scope member_scope_; + + object_section* section_; + +protected: + semantics::data_member* + id () const + { + if (root_ != 0) + return root_id_ ? root_ : 0; // Cannot have ids below root. + else + { + assert (!member_path_.empty ()); + return context::id (member_path_); + } + } + + string + column_type () + { + if (member_path_.empty ()) + { + assert (root_ != 0); + return context::column_type (*root_, key_prefix_); + } + else + return context::column_type ( + member_path_, key_prefix_, root_ != 0 && (root_id_ || root_op_)); + } + + bool + null () const + { + return (root_ != 0 && root_null_) || context::null (member_path_); + } + +private: + semantics::data_member* root_; // Root member if traversing from a member. + bool root_id_; // True if traversing root as object id. + bool root_op_; // True if traversing root as object pointer. + bool root_null_; // True if root is null-able. + +private: + void + init () + { + *this >> names_ >> member_; + *this >> inherits_ >> *this; + } + +private: + virtual void + traverse_member (semantics::data_member&, semantics::type&); + + struct member: traversal::data_member, context + { + member (object_columns_base& oc): oc_ (oc) {} + + virtual void + traverse (semantics::data_member&); + + public: + object_columns_base& oc_; + }; + + bool traverse_poly_base_; + + bool first_; + bool top_level_; + + member member_; + traversal::names names_; + traversal::inherits inherits_; +}; + +struct object_columns_list: object_columns_base +{ + typedef object_columns_list base; + + object_columns_list (bool ignore_inverse = true) + : ignore_inverse_ (ignore_inverse) + { + } + + object_columns_list (column_prefix const& cp, bool ignore_inverse = true) + : object_columns_base (true, cp), ignore_inverse_ (ignore_inverse) + { + } + + struct column + { + column (std::string const& n, + std::string const& t, + semantics::data_member& m) + : name (n), type (t), member (&m) + { + } + + std::string name; + std::string type; + semantics::data_member* member; + }; + + typedef std::vector<column> columns; + typedef columns::const_iterator iterator; + + iterator + begin () const {return columns_.begin ();} + + iterator + end () const {return columns_.end ();} + + columns::size_type + size () const {return columns_.size ();} + + virtual void + traverse_pointer (semantics::data_member&, semantics::class_&); + + virtual bool + traverse_column (semantics::data_member&, string const&, bool); + +private: + bool ignore_inverse_; + columns columns_; +}; + +// Traverse objects, views, and composite values that are class template +// instantiations. +// +struct typedefs: traversal::typedefs, context +{ + typedefs (bool traverse_included) + : included_ (traverse_included) + { + } + + virtual void + traverse (semantics::typedefs&); + + // Returns true if we should traverse this typedef. + // + bool + check (semantics::typedefs&); + +private: + bool included_; +}; + +// Other common parts. +// +#include <odb/common-query.hxx> + +#endif // ODB_COMMON_HXX |