From e4c22d3686da0e973e21eae0561c1169c0eeff36 Mon Sep 17 00:00:00 2001 From: Boris Kolpackov Date: Thu, 26 Mar 2009 17:09:53 +0200 Subject: Implement support for XML Schema polymorphism in C++/Hybrid examples/cxx/hybrid/polyroot/ examples/cxx/hybrid/polymorphism/: new examples tests/cxx/hybrid/polymorphism/: new tests --- xsde/cxx/hybrid/serializer-aggregate-header.cxx | 330 ++++++++++++++++++------ 1 file changed, 255 insertions(+), 75 deletions(-) (limited to 'xsde/cxx/hybrid/serializer-aggregate-header.cxx') diff --git a/xsde/cxx/hybrid/serializer-aggregate-header.cxx b/xsde/cxx/hybrid/serializer-aggregate-header.cxx index b697715..3e3260f 100644 --- a/xsde/cxx/hybrid/serializer-aggregate-header.cxx +++ b/xsde/cxx/hybrid/serializer-aggregate-header.cxx @@ -4,6 +4,8 @@ // license : GNU GPL v2 + exceptions; see accompanying LICENSE file #include +#include +#include #include #include @@ -17,10 +19,6 @@ namespace CXX { namespace { - typedef - Cult::Containers::Map - TypeInstanceMap; - typedef Cult::Containers::Set InstanceSet; // For base types we only want member's types, but not the @@ -108,8 +106,15 @@ namespace CXX Context { - SerializerDef (Context& c, TypeInstanceMap& map, InstanceSet& set) - : Context (c), map_ (map), set_ (set), base_ (c) + SerializerDef (Context& c, + TypeInstanceMap& map, + TypeIdInstanceMap& tid_map, + InstanceSet& set) + : Context (c), + map_ (map), + tid_map_ (tid_map), + set_ (set), + base_ (c) { *this >> inherits_ >> base_ >> inherits_; @@ -136,8 +141,10 @@ namespace CXX { if (map_.find (&t) == map_.end ()) { - String inst (find_instance_name (t)); - map_[&t] = inst; + map_[&t] = find_instance_name (t); + + if (polymorphic (t)) + collect (t); } } @@ -146,10 +153,11 @@ namespace CXX { if (map_.find (&l) == map_.end ()) { - String inst (find_instance_name (l)); - map_[&l] = inst; - + map_[&l] = find_instance_name (l); dispatch (l.argumented ().type ()); + + if (polymorphic (l)) + collect (l); } } @@ -158,8 +166,7 @@ namespace CXX { if (map_.find (&c) == map_.end ()) { - String inst (find_instance_name (c)); - map_[&c] = inst; + map_[&c] = find_instance_name (c); // Use base type's serializers in case of a restriction // since we are not capable of using a derived type @@ -172,6 +179,38 @@ namespace CXX names (c); contains_compositor (c); } + + if (polymorphic (c)) + collect (c); + } + } + + virtual Void + collect (SemanticGraph::Type& t) + { + using SemanticGraph::Type; + + for (Type::BegetsIterator i (t.begets_begin ()); + i != t.begets_end (); + ++i) + { + Type& d (i->derived ()); + + String id (d.name ()); + if (String ns = xml_ns_name (d)) + { + id += L' '; + id += ns; + } + + dispatch (d); + + if (tid_map_.find (id) == tid_map_.end ()) + { + tid_map_[id].type = &d; + tid_map_[id].name = map_.find (&d)->second; + collect (d); + } } } @@ -475,10 +514,7 @@ namespace CXX fund_type (SemanticGraph::Type& t, String const& name) { if (map_.find (&t) == map_.end ()) - { - String inst (find_instance_name (name)); - map_[&t] = inst; - } + map_[&t] = find_instance_name (name); } String @@ -504,6 +540,7 @@ namespace CXX } TypeInstanceMap& map_; + TypeIdInstanceMap& tid_map_; InstanceSet& set_; BaseType base_; @@ -535,37 +572,65 @@ namespace CXX if (!tc.count ("saggr")) return; + Boolean poly (polymorphic (t)); String const& name (tc.get ("saggr")); - String pre (unclash (name, "pre")); - String post (unclash (name, "post")); + String pre; + String post; String root_serializer (unclash (name, "root_serializer")); + String root_map; String error, reset; + String serializer_map, serializer_map_entries; InstanceSet set; - set.insert (pre); - set.insert (post); set.insert (name); set.insert (root_serializer); - if (!exceptions) + if (poly) + { + root_map = unclash (name, "root_map"); + set.insert (root_map); + } + else + { + pre = unclash (name, "pre"); + post = unclash (name, "post"); + + set.insert (pre); + set.insert (post); + } + + if (!poly && !exceptions) { error = unclash (name, "_error"); set.insert (error); } - if (Context::reset) + if (!poly && Context::reset) { reset = unclash (name, "reset"); set.insert (reset); } + if (poly_code) + { + serializer_map = unclash (name, "serializer_map_"); + serializer_map_entries = unclash (name, "serializer_map_entries_"); + + tc.set ("saggr-serializer-map", serializer_map); + tc.set ("saggr-serializer-map-entries", serializer_map_entries); + } + tc.set ("saggr-map", TypeInstanceMap ()); TypeInstanceMap& map (tc.get ("saggr-map")); + TypeIdInstanceMap tid_map; - SerializerDef def (*this, map, set); + SerializerDef def (*this, map, tid_map, set); def.dispatch (t); + if (poly_code && !tid_map.empty ()) + tc.set ("saggr-tid-map", tid_map); + String const& root_member (map.find (&t)->second); os << "// Serializer aggregate for the " << comment (t.name ()) << @@ -581,29 +646,32 @@ namespace CXX os << name << " ();" << endl; - // pre () - // - String const& arg (sarg_type (t)); + if (!poly) + { + // pre () + // + String const& arg (sarg_type (t)); - os << "void" << endl - << pre << " ("; + os << "void" << endl + << pre << " ("; - if (arg != L"void") - os << arg << " x"; + if (arg != L"void") + os << arg << " x"; - os <<")" - << "{" - << "this->" << root_member << ".pre (" << - (arg != L"void" ? "x" : "") << ");" - << "}"; + os <<")" + << "{" + << "this->" << root_member << ".pre (" << + (arg != L"void" ? "x" : "") << ");" + << "}"; - // post () - // - os << "void" << endl - << post << " ()" - << "{" - << "this->" << root_member << ".post ();" - << "}"; + // post () + // + os << "void" << endl + << post << " ()" + << "{" + << "this->" << root_member << ".post ();" + << "}"; + } // root_serializer () // @@ -613,9 +681,23 @@ namespace CXX << "return this->" << root_member << ";" << "}"; + if (poly) + { + // root_map () + // + if (poly) + { + os << "const " << xs_ns_name () + L"::serializer_map&" << endl + << root_map << " ()" + << "{" + << "return this->" << serializer_map << ";" + << "}"; + } + } + // _error () // - if (error) + if (!poly && error) { os << xs_ns_name () << "::serializer_error" << endl << error << " ()" @@ -631,8 +713,12 @@ namespace CXX os << "void" << endl << reset << " ()" << "{" - << "this->" << root_member << "._reset ();" - << "}"; + << "this->" << root_member << "._reset ();"; + + if (poly && tid_map.size () > 0) + os << "this->" << serializer_map << ".reset ();"; + + os << "}"; } os << "public:" << endl; @@ -641,6 +727,15 @@ namespace CXX i != end; ++i) os << fq_name (*i->first, "s:impl") << " " << i->second << ";"; + if (tid_map.size () > 0) + { + os << endl + << "::xsde::cxx::hybrid::serializer_map_impl " << + serializer_map << ";" + << "::xsde::cxx::hybrid::serializer_map_impl::entry " << + serializer_map_entries << "[" << tid_map.size () << "UL];"; + } + os << "};"; } }; @@ -661,41 +756,70 @@ namespace CXX return; SemanticGraph::Type& t (e.type ()); + Boolean poly (polymorphic (t)); String const& name (ec.get ("saggr")); - String pre (unclash (name, "pre")); - String post (unclash (name, "post")); + String pre; + String post; String root_serializer (unclash (name, "root_serializer")); + String root_map; String root_name (unclash (name, "root_name")); String root_namespace (unclash (name, "root_namespace")); String error, reset; + String serializer_map, serializer_map_entries; InstanceSet set; - set.insert (pre); - set.insert (post); set.insert (name); set.insert (root_serializer); + + if (poly) + { + root_map = unclash (name, "root_map"); + set.insert (root_map); + } + else + { + pre = unclash (name, "pre"); + post = unclash (name, "post"); + + set.insert (pre); + set.insert (post); + } + set.insert (root_name); set.insert (root_namespace); - if (!exceptions) + if (!poly && !exceptions) { error = unclash (name, "_error"); set.insert (error); } - if (Context::reset) + if (!poly && Context::reset) { reset = unclash (name, "reset"); set.insert (reset); } + if (poly_code) + { + serializer_map = unclash (name, "serializer_map_"); + serializer_map_entries = unclash (name, "serializer_map_entries_"); + + ec.set ("saggr-serializer-map", serializer_map); + ec.set ("saggr-serializer-map-entries", serializer_map_entries); + } + ec.set ("saggr-map", TypeInstanceMap ()); TypeInstanceMap& map (ec.get ("saggr-map")); + TypeIdInstanceMap tid_map; - SerializerDef def (*this, map, set); + SerializerDef def (*this, map, tid_map, set); def.dispatch (t); + if (poly_code && !tid_map.empty ()) + ec.set ("saggr-tid-map", tid_map); + String const& root_member (map.find (&t)->second); os << "// Serializer aggregate for the " << comment (e.name ()) << @@ -711,29 +835,32 @@ namespace CXX os << name << " ();" << endl; - // pre () - // - String const& arg (sarg_type (t)); + if (!poly) + { + // pre () + // + String const& arg (sarg_type (t)); - os << "void" << endl - << pre << " ("; + os << "void" << endl + << pre << " ("; - if (arg != L"void") - os << arg << " x"; + if (arg != L"void") + os << arg << " x"; - os <<")" - << "{" - << "this->" << root_member << ".pre (" << - (arg != L"void" ? "x" : "") << ");" - << "}"; + os <<")" + << "{" + << "this->" << root_member << ".pre (" << + (arg != L"void" ? "x" : "") << ");" + << "}"; - // post () - // - os << "void" << endl - << post << " ()" - << "{" - << "this->" << root_member << ".post ();" - << "}"; + // post () + // + os << "void" << endl + << post << " ()" + << "{" + << "this->" << root_member << ".post ();" + << "}"; + } // root_serializer () // @@ -743,6 +870,20 @@ namespace CXX << "return this->" << root_member << ";" << "}"; + if (poly) + { + // root_map () + // + if (poly) + { + os << "const " << xs_ns_name () + L"::serializer_map&" << endl + << root_map << " ()" + << "{" + << "return this->" << serializer_map << ";" + << "}"; + } + } + // root_name () // os << "static const char*" << endl @@ -757,7 +898,7 @@ namespace CXX // _error () // - if (error) + if (!poly && error) { os << xs_ns_name () << "::serializer_error" << endl << error << " ()" @@ -773,8 +914,12 @@ namespace CXX os << "void" << endl << reset << " ()" << "{" - << "this->" << root_member << "._reset ();" - << "}"; + << "this->" << root_member << "._reset ();"; + + if (poly && tid_map.size () > 0) + os << "this->" << serializer_map << ".reset ();"; + + os << "}"; } os << "public:" << endl; @@ -783,6 +928,15 @@ namespace CXX i != end; ++i) os << fq_name (*i->first, "s:impl") << " " << i->second << ";"; + if (tid_map.size () > 0) + { + os << endl + << "::xsde::cxx::hybrid::serializer_map_impl " << + serializer_map << ";" + << "::xsde::cxx::hybrid::serializer_map_impl::entry " << + serializer_map_entries << "[" << tid_map.size () << "UL];"; + } + os << "};"; } }; @@ -811,6 +965,10 @@ namespace CXX if (gen) { + if (ctx.poly_code) + ctx.os << "#include " << endl + << endl; + // Emit "weak" header includes that are used in the file-per-type // compilation model. // @@ -823,6 +981,28 @@ namespace CXX schema.dispatch (ctx.schema_root); } + // Emit includes for additional schemas that define derived + // polymorphic types. + // + if (ctx.poly_code) + { + Traversal::Schema schema; + Traversal::Sources sources; + + schema >> sources >> schema; + + Traversal::Names schema_names; + Traversal::Namespace ns; + Traversal::Names names; + AggregateInclude include (ctx, "saggr"); + + schema >> schema_names >> ns >> names >> include; + + schema.dispatch (ctx.schema_root); + } + + // Generate code. + // Traversal::Schema schema; Traversal::Sources sources; -- cgit v1.1