summaryrefslogtreecommitdiff
path: root/odb/odb/common.cxx
diff options
context:
space:
mode:
Diffstat (limited to 'odb/odb/common.cxx')
-rw-r--r--odb/odb/common.cxx584
1 files changed, 584 insertions, 0 deletions
diff --git a/odb/odb/common.cxx b/odb/odb/common.cxx
new file mode 100644
index 0000000..63e49ad
--- /dev/null
+++ b/odb/odb/common.cxx
@@ -0,0 +1,584 @@
+// file : odb/common.cxx
+// license : GNU GPL v3; see accompanying LICENSE file
+
+#include <odb/common.hxx>
+
+using namespace std;
+
+//
+// object_members_base
+//
+
+void object_members_base::
+traverse_simple (semantics::data_member&)
+{
+}
+
+void object_members_base::
+traverse_pointer (semantics::data_member& m, semantics::class_& c)
+{
+ if (!view_member (m)) // Not really "as if" pointed-to id member.
+ traverse_member (m, utype (*id_member (c)));
+}
+
+void object_members_base::
+traverse_composite (semantics::data_member*, semantics::class_& c)
+{
+ inherits (c);
+ names (c);
+}
+
+void object_members_base::
+traverse_composite_wrapper (semantics::data_member* m,
+ semantics::class_& c,
+ semantics::type*)
+{
+ traverse_composite (m, c);
+}
+
+void object_members_base::
+traverse_container (semantics::data_member&, semantics::type&)
+{
+}
+
+void object_members_base::
+traverse_object (semantics::class_& c)
+{
+ inherits (c);
+ names (c);
+}
+
+void object_members_base::
+traverse_view (semantics::class_& c)
+{
+ // A view has no bases.
+ //
+ names (c);
+}
+
+void object_members_base::
+traverse (semantics::class_& c)
+{
+ class_kind_type k (class_kind (c));
+
+ if (k == class_other)
+ {
+ // Ignore transient bases.
+ //
+ return;
+ }
+ else if (k == class_composite)
+ {
+ if (member_scope_.empty ())
+ member_scope_.push_back (class_inheritance_chain ());
+
+ member_scope_.back ().push_back (&c);
+
+ traverse_composite_wrapper (0, c, 0);
+
+ member_scope_.back ().pop_back ();
+
+ if (member_scope_.back ().empty ())
+ member_scope_.pop_back ();
+
+ return;
+ }
+
+ if (top_level_)
+ top_level_ = false;
+ else
+ {
+ // Unless requested otherwise, don't go into bases if we are a derived
+ // type in a polymorphic hierarchy.
+ //
+ if (!traverse_poly_base_ && polymorphic (c))
+ return;
+ }
+
+ if (context::top_object == 0)
+ context::top_object = &c;
+
+ semantics::class_* prev (context::cur_object);
+ context::cur_object = &c;
+
+ if (member_scope_.empty ())
+ member_scope_.push_back (class_inheritance_chain ());
+
+ member_scope_.back ().push_back (&c);
+
+ if (build_table_prefix_)
+ {
+ // Don't reset the table prefix if we are traversing a base.
+ //
+ bool tb (false);
+
+ if (table_prefix_.level == 0)
+ {
+ table_prefix_ = table_prefix (c);
+ tb = true;
+ }
+
+ if (k == class_object)
+ traverse_object (c);
+ else
+ traverse_view (c);
+
+ if (tb)
+ table_prefix_ = table_prefix ();
+ }
+ else
+ {
+ if (k == class_object)
+ traverse_object (c);
+ else
+ traverse_view (c);
+ }
+
+ member_scope_.back ().pop_back ();
+
+ if (member_scope_.back ().empty ())
+ member_scope_.pop_back ();
+
+ context::cur_object = prev;
+
+ if (prev == 0)
+ context::top_object = 0;
+}
+
+void object_members_base::
+traverse_member (semantics::data_member& m, semantics::type& t)
+{
+ if (semantics::class_* comp = context::composite_wrapper (t))
+ {
+ member_scope_.push_back (class_inheritance_chain ());
+ member_scope_.back ().push_back (comp);
+
+ table_prefix old_table_prefix;
+ string old_flat_prefix, old_member_prefix;
+
+ if (build_flat_prefix_)
+ {
+ old_flat_prefix = flat_prefix_;
+ flat_prefix_ += public_name (m);
+ flat_prefix_ += '_';
+ }
+
+ if (build_member_prefix_)
+ {
+ old_member_prefix = member_prefix_;
+ member_prefix_ += m.name ();
+ member_prefix_ += '.';
+ }
+
+ if (build_table_prefix_)
+ {
+ old_table_prefix = table_prefix_;
+ table_prefix_.append (m);
+ }
+
+ traverse_composite_wrapper (&m, *comp, (wrapper (t) ? &t : 0));
+
+ if (build_table_prefix_)
+ table_prefix_ = old_table_prefix;
+
+ if (build_flat_prefix_)
+ flat_prefix_ = old_flat_prefix;
+
+ if (build_member_prefix_)
+ member_prefix_ = old_member_prefix;
+
+ member_scope_.pop_back ();
+ }
+ else
+ traverse_simple (m);
+}
+
+bool object_members_base::
+section_test (data_member_path const& mp)
+{
+ // By default ignore members from the wrong section.
+ //
+ return section_ == 0 || *section_ == section (mp);
+}
+
+void object_members_base::member::
+traverse (semantics::data_member& m)
+{
+ if (transient (m))
+ return;
+
+ om_.member_path_.push_back (&m);
+
+ // Ignore members from the wrong section.
+ //
+ if (om_.section_test (om_.member_path_))
+ {
+ semantics::type& t (utype (m));
+
+ if (semantics::type* c = context::container (m))
+ om_.traverse_container (m, *c);
+ else if (semantics::class_* c = object_pointer (t))
+ om_.traverse_pointer (m, *c);
+ else
+ om_.traverse_member (m, t);
+ }
+
+ om_.member_path_.pop_back ();
+}
+
+//
+// object_columns_base
+//
+
+void object_columns_base::
+flush ()
+{
+}
+
+bool object_columns_base::
+traverse_column (semantics::data_member&, string const&, bool)
+{
+ return false;
+}
+
+void object_columns_base::
+traverse_pointer (semantics::data_member& m, semantics::class_& c)
+{
+ if (!view_member (m)) // Not really "as if" pointed-to id column.
+ traverse_member (m, utype (*id_member (c)));
+}
+
+void object_columns_base::
+traverse_points_to (semantics::data_member& m, semantics::class_&)
+{
+ traverse_member (m, utype (m));
+}
+
+void object_columns_base::
+traverse_composite (semantics::data_member*, semantics::class_& c)
+{
+ inherits (c);
+ names (c);
+}
+
+void object_columns_base::
+traverse_object (semantics::class_& c)
+{
+ inherits (c);
+ names (c);
+}
+
+void object_columns_base::
+traverse_view (semantics::class_& c)
+{
+ // A view has no bases.
+ //
+ names (c);
+}
+
+void object_columns_base::
+traverse_pre (semantics::nameable&)
+{
+}
+
+void object_columns_base::
+traverse_post (semantics::nameable&)
+{
+}
+
+void object_columns_base::
+traverse (semantics::data_member& m)
+{
+ traverse_pre (m);
+
+ semantics::type& t (utype (m));
+ semantics::class_* c (object_pointer (t));
+ semantics::type* rt (c == 0 ? &t : &utype (*id_member (*c)));
+
+ root_ = &m;
+
+ // It would seem natural to add m to member_path_ so that we don't
+ // have these two cases. However, for member path to work correctly
+ // with readonly() we also have to have corresponding member_scope,
+ // which is a whole different level of complexity.
+ //
+ root_id_ = member_path_.empty ()
+ ? context::id (m)
+ : context::id (member_path_) != 0;
+ root_op_ = (c != 0);
+ root_null_ = context::null (m);
+
+
+ if (root_op_)
+ traverse_pointer (m, *c);
+ else
+ traverse_member (m, *rt);
+
+ if (!first_ && composite_wrapper (*rt))
+ flush ();
+
+ root_ = 0;
+
+ traverse_post (m);
+}
+
+void object_columns_base::
+traverse (semantics::data_member& m,
+ semantics::type& t,
+ std::string const& kp,
+ std::string const& dn,
+ semantics::class_* to)
+{
+ traverse_pre (m);
+
+ semantics::class_* oto (context::top_object);
+
+ if (to != 0)
+ context::top_object = to;
+
+ semantics::class_* c (object_pointer (t));
+ semantics::type* rt (c == 0 ? &t : &utype (*id_member (*c)));
+
+ root_ = &m;
+ root_id_ = (kp == "id");
+ root_op_ = (c != 0);
+ root_null_ = context::null (m, kp);
+
+ key_prefix_ = kp;
+ default_name_ = dn;
+
+ if (root_op_)
+ traverse_pointer (m, *c);
+ else
+ traverse_member (m, *rt);
+
+ key_prefix_.clear ();
+ default_name_.clear ();
+
+ if (!first_ && composite_wrapper (*rt))
+ flush ();
+
+ root_ = 0;
+ context::top_object = oto;
+
+ traverse_post (m);
+}
+
+void object_columns_base::
+traverse (semantics::class_& c)
+{
+ class_kind_type k (class_kind (c));
+
+ // Ignore transient bases.
+ //
+ if (k == class_other)
+ return;
+
+ bool f (top_level_);
+
+ if (top_level_)
+ {
+ traverse_pre (c);
+ top_level_ = false;
+ }
+ else
+ {
+ // Unless requested otherwise, don't go into bases if we are a derived
+ // type in a polymorphic hierarchy.
+ //
+ if (!traverse_poly_base_ && polymorphic (c))
+ return;
+ }
+
+ semantics::class_* prev (0);
+ if (k == class_object || k == class_view)
+ {
+ if (context::top_object == 0)
+ context::top_object = &c;
+
+ prev = context::cur_object;
+ context::cur_object = &c;
+ }
+
+ if (member_scope_.empty ())
+ member_scope_.push_back (class_inheritance_chain ());
+
+ member_scope_.back ().push_back (&c);
+
+ if (k == class_object)
+ traverse_object (c);
+ else if (k == class_view)
+ traverse_view (c);
+ else if (k == class_composite)
+ traverse_composite (0, c);
+
+ member_scope_.back ().pop_back ();
+
+ if (member_scope_.back ().empty ())
+ member_scope_.pop_back ();
+
+ if (k == class_object || k == class_view)
+ {
+ context::cur_object = prev;
+
+ if (prev == 0)
+ context::top_object = 0;
+ }
+
+ if (f)
+ {
+ if (!first_)
+ flush ();
+
+ traverse_post (c);
+ }
+}
+
+void object_columns_base::
+traverse_member (semantics::data_member& m, semantics::type& t)
+{
+ if (semantics::class_* comp = composite_wrapper (t))
+ {
+ member_scope_.push_back (class_inheritance_chain ());
+ member_scope_.back ().push_back (comp);
+
+ column_prefix old_prefix (column_prefix_);
+ column_prefix_.append (m, key_prefix_, default_name_);
+
+ // Save and clear the key prefix and default name.
+ //
+ string old_kp, old_dn;
+ old_kp.swap (key_prefix_);
+ old_dn.swap (default_name_);
+
+ traverse_composite (&m, *comp);
+
+ old_kp.swap (key_prefix_);
+ old_dn.swap (default_name_);
+
+ column_prefix_ = old_prefix;
+ member_scope_.pop_back ();
+ }
+ else
+ {
+ string name (column_name (m, key_prefix_, default_name_, column_prefix_));
+
+ if (traverse_column (m, name, first_))
+ {
+ if (first_)
+ first_ = false;
+ }
+ }
+}
+
+bool object_columns_base::
+section_test (data_member_path const& mp)
+{
+ // By default ignore members from the wrong section.
+ //
+ return section_ == 0 || *section_ == section (mp);
+}
+
+void object_columns_base::member::
+traverse (semantics::data_member& m)
+{
+ if (transient (m))
+ return;
+
+ // Container gets its own table, so nothing to do here.
+ //
+ if (container (m))
+ return;
+
+ oc_.member_path_.push_back (&m);
+
+ if (oc_.section_test (oc_.member_path_))
+ {
+ using semantics::class_;
+ semantics::type& t (utype (m));
+
+ if (class_* c = object_pointer (t))
+ oc_.traverse_pointer (m, *c);
+ else if (class_* c = points_to (m))
+ oc_.traverse_points_to (m, *c);
+ else
+ oc_.traverse_member (m, t);
+ }
+
+ oc_.member_path_.pop_back ();
+}
+
+//
+// object_columns_list
+//
+
+void object_columns_list::
+traverse_pointer (semantics::data_member& m, semantics::class_& c)
+{
+ // Ignore inverse object pointers.
+ //
+ if (!ignore_inverse_ || !inverse (m, key_prefix_))
+ object_columns_base::traverse_pointer (m, c);
+}
+
+bool object_columns_list::
+traverse_column (semantics::data_member& m, std::string const& name, bool)
+{
+ columns_.push_back (column (name, column_type (), m));
+ return true;
+}
+
+//
+// typedefs
+//
+
+void typedefs::
+traverse (semantics::typedefs& t)
+{
+ if (check (t))
+ traversal::typedefs::traverse (t);
+}
+
+bool typedefs::
+check (semantics::typedefs& t)
+{
+ // This typedef must be for a class template instantiation.
+ //
+ using semantics::class_instantiation;
+ class_instantiation* ci (dynamic_cast<class_instantiation*> (&t.type ()));
+
+ if (ci == 0)
+ return false;
+
+ // It must be an object, view, or composite value.
+ //
+ if (class_kind (*ci) == class_other)
+ return false;
+
+ // This typedef name should be the one that was used in the pragma.
+ //
+ using semantics::names;
+ tree type (ci->get<tree> ("tree-node"));
+
+ names* hint;
+ if (ci->count ("tree-hint"))
+ hint = ci->get<names*> ("tree-hint");
+ else
+ {
+ hint = unit.find_hint (type);
+ ci->set ("tree-hint", hint); // Cache it.
+ }
+
+ if (hint != &t)
+ return false;
+
+ // And the definition may have to be in the file we are compiling.
+ //
+ if (!included_)
+ {
+ if (!options.at_once () && class_file (*ci) != unit.file ())
+ return false;
+ }
+
+ return true;
+}