aboutsummaryrefslogtreecommitdiff
path: root/xsde/cxx/hybrid/serializer-aggregate-header.cxx
diff options
context:
space:
mode:
authorBoris Kolpackov <boris@codesynthesis.com>2009-03-26 17:09:53 +0200
committerBoris Kolpackov <boris@codesynthesis.com>2009-03-26 17:09:53 +0200
commite4c22d3686da0e973e21eae0561c1169c0eeff36 (patch)
tree0a49e9167edc88938b0287949080931314e8afea /xsde/cxx/hybrid/serializer-aggregate-header.cxx
parent0d62005a3ff3b62d02c2eb3fd8644e0e19b202e8 (diff)
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
Diffstat (limited to 'xsde/cxx/hybrid/serializer-aggregate-header.cxx')
-rw-r--r--xsde/cxx/hybrid/serializer-aggregate-header.cxx330
1 files changed, 255 insertions, 75 deletions
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 <cxx/hybrid/serializer-aggregate-header.hxx>
+#include <cxx/hybrid/aggregate-elements.hxx>
+#include <cxx/hybrid/aggregate-include.hxx>
#include <xsd-frontend/semantic-graph.hxx>
#include <xsd-frontend/traversal.hxx>
@@ -17,10 +19,6 @@ namespace CXX
{
namespace
{
- typedef
- Cult::Containers::Map<SemanticGraph::Type*, String>
- TypeInstanceMap;
-
typedef Cult::Containers::Set<String> 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<String> ("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<TypeInstanceMap> ("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<String> ("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<TypeInstanceMap> ("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 <xsde/cxx/hybrid/serializer-map.hxx>" << 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;