diff options
Diffstat (limited to 'xsde/cxx/serializer/serializer-source.cxx')
-rw-r--r-- | xsde/cxx/serializer/serializer-source.cxx | 2703 |
1 files changed, 2703 insertions, 0 deletions
diff --git a/xsde/cxx/serializer/serializer-source.cxx b/xsde/cxx/serializer/serializer-source.cxx new file mode 100644 index 0000000..ec30add --- /dev/null +++ b/xsde/cxx/serializer/serializer-source.cxx @@ -0,0 +1,2703 @@ +// file : xsde/cxx/serializer/serializer-source.cxx +// author : Boris Kolpackov <boris@codesynthesis.com> +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#include <cxx/serializer/serializer-source.hxx> + +#include <xsd-frontend/semantic-graph.hxx> +#include <xsd-frontend/traversal.hxx> + +namespace CXX +{ + namespace Serializer + { + namespace + { + // Override classes override pure virtual functions in the base. + // Should be in sync with definition generators below. Used in + // tiein implementation. + // + + struct CompositorCallbackOverride: Traversal::Choice, + Traversal::Sequence, + Context + { + CompositorCallbackOverride (Context& c, String const& scope) + : Context (c), scope_ (scope) + { + } + + virtual Void + traverse (SemanticGraph::Choice& c) + { + if (c.contains_begin () != c.contains_end ()) + { + UnsignedLong min (c.min ()), max (c.max ()); + + if (min != 0) + { + SemanticGraph::Type& t ( + dynamic_cast<SemanticGraph::Type&> (scope (c))); + + String const& impl (etiein (t)); + + if (max != 1) + { + String const& next (enext (c)); + + os << "bool " << scope_ << "::" << endl + << next << " ()" + << "{" + << "assert (this->" << impl << ");" + << "return this->" << impl << "->" << next << " ();" + << "}"; + } + + String const& arm (earm (c)); + + os << fq_name (t) << "::" << earm_tag (c) << " " << + scope_ << "::" << endl + << arm << " ()" + << "{" + << "assert (this->" << impl << ");" + << "return this->" << impl << "->" << arm << " ();" + << "}"; + } + + Traversal::Choice::traverse (c); + } + } + + virtual Void + traverse (SemanticGraph::Sequence& s) + { + UnsignedLong min (s.min ()), max (s.max ()); + + if (max != 1 && min != 0) + { + String const& impl ( + etiein (dynamic_cast<SemanticGraph::Type&> (scope (s)))); + + String const& next (enext (s)); + + os << "bool " << scope_ << "::" << endl + << next << " ()" + << "{" + << "assert (this->" << impl << ");" + << "return this->" << impl << "->" << next << " ();" + << "}"; + } + + Traversal::Sequence::traverse (s); + } + + private: + SemanticGraph::Scope& + scope (SemanticGraph::Compositor& c) + { + SemanticGraph::Compositor* root (&c); + + while (root->contained_particle_p ()) + root = &root->contained_particle ().compositor (); + + return dynamic_cast<SemanticGraph::Scope&> ( + root->contained_compositor ().container ()); + } + + private: + String const& scope_; + }; + + struct ParticleCallbackOverride: Traversal::Element, + Traversal::Any, + Context + { + ParticleCallbackOverride (Context& c, String const& scope) + : Context (c), scope_ (scope) + { + } + + virtual Void + traverse (SemanticGraph::Element& e) + { + UnsignedLong min (e.min ()), max (e.max ()); + + String const& impl ( + etiein (dynamic_cast<SemanticGraph::Type&> (e.scope ()))); + + if (max != 1 && min != 0) + { + String const& next (enext (e)); + + os << "bool " << scope_ << "::" << endl + << next << " ()" + << "{" + << "assert (this->" << impl << ");" + << "return this->" << impl << "->" << next << " ();" + << "}"; + } + + String const& ret (ret_type (e.type ())); + + if (ret != L"void") + { + String const& name (ename (e)); + + os << ret << " " << scope_ << "::" << endl + << name << " ()" + << "{" + << "assert (this->" << impl << ");" + << "return this->" << impl << "->" << name << " ();" + << "}"; + } + } + + virtual Void + traverse (SemanticGraph::Any& a) + { + UnsignedLong min (a.min ()), max (a.max ()); + + if (min != 0 && + !a.contained_particle ().compositor ().is_a< + SemanticGraph::Choice> ()) + { + String const& impl ( + etiein (dynamic_cast<SemanticGraph::Type&> (a.scope ()))); + + if (max != 1) + { + String const& next (enext (a)); + + os << "bool " << scope_ << "::" << endl + << next << " ()" + << "{" + << "assert (this->" << impl << ");" + << "return this->" << impl << "->" << next << " ();" + << "}"; + } + + String const& name (ename (a)); + + if (stl) + { + os << "void " << scope_ << "::" << endl + << name << " (::std::string& ns, ::std::string& name)" + << "{" + << "assert (this->" << impl << ");" + << "this->" << impl << "->" << name << " (ns, name);" + << "}"; + } + else + { + os << "void " << scope_ << "::" << endl + << name << " (const char*& ns, const char*& name, " << + "bool& free)" + << "{" + << "assert (this->" << impl << ");" + << "this->" << impl << "->" << name << " (ns, name, free);" + << "}"; + } + + String const& serialize (eserialize (a)); + + os << "void " << scope_ << "::" << endl + << serialize << " ()" + << "{" + << "assert (this->" << impl << ");" + << "this->" << impl << "->" << serialize << " ();" + << "}"; + } + } + + private: + String const& scope_; + }; + + struct AttributeCallbackOverride: Traversal::Attribute, Context + { + AttributeCallbackOverride (Context& c, String const& scope) + : Context (c), scope_ (scope) + { + } + + virtual Void + traverse (SemanticGraph::Attribute& a) + { + String const& ret (ret_type (a.type ())); + + if (ret != L"void") + { + String const& impl ( + etiein (dynamic_cast<SemanticGraph::Type&> (a.scope ()))); + + String const& name (ename (a)); + + os << ret << " " << scope_ << "::" << endl + << name << " ()" + << "{" + << "assert (this->" << impl << ");" + << "return this->" << impl << "->" << name << " ();" + << "}"; + } + } + + private: + String const& scope_; + }; + + struct BaseOverride: Traversal::Type, + Traversal::Enumeration, + Traversal::List, + Traversal::Union, + Traversal::Complex, + Context + { + BaseOverride (Context& c, String const& scope) + : Context (c), + scope_ (scope), + compositor_callback_ (c, scope), + particle_callback_ (c, scope), + attribute_callback_ (c, scope) + { + contains_compositor_callback_ >> compositor_callback_; + compositor_callback_ >> contains_particle_callback_; + contains_particle_callback_ >> compositor_callback_; + contains_particle_callback_ >> particle_callback_; + + names_attribute_callback_ >> attribute_callback_; + } + + virtual Void + traverse (SemanticGraph::Type& t) + { + // pre + // + String const& arg (arg_type (t)); + + if (arg != L"void") + { + String const& impl (etiein (t)); + + os << "void " << scope_ << "::" << endl + << "pre (" << arg << " x)" + << "{" + << "assert (this->" << impl << ");" + << "this->" << impl << "->pre (x);" + << "}"; + } + } + + virtual Void + traverse (SemanticGraph::Enumeration& e) + { + SemanticGraph::Type& t (e); + traverse (t); + } + + virtual Void + traverse (SemanticGraph::List& l) + { + SemanticGraph::Type& t (l); + traverse (t); + + // item + // + String const& ret (ret_type (l.argumented ().type ())); + + if (ret != L"void") + { + String item (unclash (ename (l), "item")); + String const& impl (etiein (l)); + + os << ret << " " << scope_ << "::" << endl + << item << " ()" + << "{" + << "assert (this->" << impl << ");" + << "return this->" << impl << "->" << item << " ();" + << "}"; + } + } + + virtual Void + traverse (SemanticGraph::Union& u) + { + SemanticGraph::Type& t (u); + traverse (t); + + // serialize_content + // + String const& impl (etiein (u)); + + os << "void " << scope_ << "::" << endl + << "_serialize_content ()" + << "{" + << "assert (this->" << impl << ");" + << "this->" << impl << "->_serialize_content ();" + << "}"; + } + + virtual Void + traverse (SemanticGraph::Complex& c) + { + SemanticGraph::Type& t (c); + traverse (t); + + // Member callbacks. + // + if (!restriction_p (c)) + { + Traversal::Complex::names (c, names_attribute_callback_); + Traversal::Complex::contains_compositor ( + c, contains_compositor_callback_); + } + } + + private: + String const& scope_; + + CompositorCallbackOverride compositor_callback_; + ParticleCallbackOverride particle_callback_; + Traversal::ContainsCompositor contains_compositor_callback_; + Traversal::ContainsParticle contains_particle_callback_; + + AttributeCallbackOverride attribute_callback_; + Traversal::Names names_attribute_callback_; + }; + + // + // + + struct Enumeration: Traversal::Enumeration, Context + { + Enumeration (Context& c) + : Context (c) + { + } + + virtual Void + traverse (Type& e) + { + String const& name (ename (e)); + String const& arg (arg_type (e)); + SemanticGraph::Type& base (e.inherits ().base ()); + + os << "// " << name << endl + << "//" << endl + << endl; + + if (arg != arg_type (base) && arg == L"void") + { + os << "void " << name << "::" << endl + << "pre ()" + << "{"; + + if (tiein) + { + String const& impl (etiein (e)); + + os << "if (this->" << impl << ")" << endl + << "this->" << impl << "->pre ();"; + } + + os << "}"; + } + + if (poly_code) + { + String id (e.name ()); + + if (String ns = xml_ns_name (e)) + { + id += L' '; + id += ns; + } + + os << "const char* " << name << "::" << endl + << "_static_type ()" + << "{" + << "return " << strlit (id) << ";" + << "}"; + + os << "const char* " << name << "::" << endl + << "_dynamic_type () const" + << "{" + << "return _static_type ();" + << "}"; + + if (validation) + { + Boolean gen (!anonymous (e)); + + // We normally don't need to enter anonymous types into + // the inheritance map. The only exception is when an + // anonymous types is defined inside an element that + // is a member of a substitution group. + // + if (!gen) + { + // The first instance that this anonymous type classifies + // is the prototype for others if any. + // + SemanticGraph::Instance& i ( + e.classifies_begin ()->instance ()); + + if (SemanticGraph::Element* e = + dynamic_cast<SemanticGraph::Element*> (&i)) + { + if (e->substitutes_p ()) + gen = true; + } + } + + if (gen) + { + os << "static" << endl + << "const ::xsde::cxx::serializer::validating::" << + "inheritance_map_entry" << endl + << "_xsde_" << name << "_inheritance_map_entry_ (" << endl + << name << "::_static_type ()," << endl + << fq_name (base) << "::_static_type ());" + << endl; + } + } + } + + if (tiein) + { + // If our base has pure virtual functions, override them here. + // + BaseOverride t (*this, name); + t.dispatch (base); + } + } + }; + + // + // + struct List: Traversal::List, Context + { + List (Context& c) + : Context (c) + { + } + + virtual Void + traverse (Type& l) + { + String const& name (ename (l)); + SemanticGraph::Type& t (l.argumented ().type ()); + + String const& ret (ret_type (t)); + String const& arg (arg_type (t)); + + String item (unclash (name, "item")); + String item_next (unclash (name, "item_next")); + String inst (L"_xsde_" + item + L"_"); + + os << "// " << name << endl + << "//" << endl + << endl; + + String impl; + + if (tiein) + impl = etiein (l); + + // pre + // + if (arg_type (l) == L"void") + { + os << "void " << name << "::" << endl + << "pre ()" + << "{"; + + if (tiein) + os << "if (this->" << impl << ")" << endl + << "this->" << impl << "->pre ();"; + + os << "}"; + } + + // item + // + os << "bool " << name << "::" << endl + << item_next << " ()" + << "{"; + + if (tiein) + os << "return this->" << impl << " ? this->" << impl << "->" << + item_next << " () : false;"; + else + os << "return false;"; + + os << "}"; + + if (ret == L"void") + { + os << ret << " " << name << "::" << endl + << item << " ()" + << "{"; + + if (tiein) + os << "if (this->" << impl << ")" << endl + << "return this->" << impl << "->" << item << " ();"; + + os << "}"; + } + + // reset + // + if (reset) + { + os << "void " << name << "::" << endl + << "_reset ()" + << "{" + << simple_base << "::_reset ();" + << endl + << "if (this->" << inst << ")" << endl + << "this->" << inst << "->_reset ();" + << "}"; + } + + // serialize_content + // + os << "void " << name << "::" << endl + << "_serialize_content ()" + << "{"; + + os << "bool first = true;" + << "::xsde::cxx::serializer::context& ctx = this->_context ();" + << endl; + + if (exceptions && !validation) + { + os << "while (this->" << item_next << " ())" + << "{" + << "if (this->" << inst << ")" + << "{"; + + if (ret == L"void") + os << "this->" << item << " ();" + << "this->" << inst << "->pre ();"; + else + os << arg << " r = this->" << item << " ();" + << "this->" << inst << "->pre (r);"; + + os << endl + << "if (!first)" << endl + << "this->_characters (\" \", 1);" + << "else" << endl + << "first = false;" + << endl; + + os << "this->" << inst << "->_pre_impl (ctx);" + << "this->" << inst << "->_serialize_content ();" + << "this->" << inst << "->_post_impl ();" + << "this->" << inst << "->post ();"; + + os << "}" + << "}"; + } + else + { + os << "while (this->" << item_next << " ())" + << "{" + << "if (this->" << inst << ")" + << "{"; + + if (ret == L"void") + os << "this->" << item << " ();"; + else + os << arg << " r = this->" << item << " ();"; + + os << endl + << "if (ctx.error_type ())" << endl + << "break;" + << endl; + + if (ret == L"void") + os << "this->" << inst << "->pre ();"; + else + os << "this->" << inst << "->pre (r);"; + + if (!exceptions) + { + os << endl + << "if (this->" << inst << "->_error_type ())" << endl + << "this->" << inst << "->_copy_error (ctx);" + << endl; + + os << "if (ctx.error_type ())" << endl + << "break;"; + } + + if (!exceptions) + os << endl + << "if (!first)" + << "{" + << "if (!this->_characters (\" \", 1))" << endl + << "break;" + << "}"; + else + os << endl + << "if (!first)" << endl + << "this->_characters (\" \", 1);"; + + os << "else" << endl + << "first = false;" + << endl; + + os << "this->" << inst << "->_pre_impl (ctx);"; + + os << endl + << "if (ctx.error_type ())" << endl + << "break;" + << endl; + + os << "this->" << inst << "->_serialize_content ();"; + + os << endl + << "if (ctx.error_type ())" << endl + << "break;" + << endl; + + os << "this->" << inst << "->_post_impl ();"; + + os << endl + << "if (ctx.error_type ())" << endl + << "break;" + << endl; + + os << "this->" << inst << "->post ();"; + + if (!exceptions) + { + os << endl + << "if (this->" << inst << "->_error_type ())" << endl + << "this->" << inst << "->_copy_error (ctx);" + << endl; + + os << "if (ctx.error_type ())" << endl + << "break;"; + } + + os << "}" // No check for error here since we return anyway. + << "}"; + } + + os << "}"; // _serialize_content + + // + // + if (poly_code) + { + String id (l.name ()); + + if (String ns = xml_ns_name (l)) + { + id += L' '; + id += ns; + } + + os << "const char* " << name << "::" << endl + << "_static_type ()" + << "{" + << "return " << strlit (id) << ";" + << "}"; + + os << "const char* " << name << "::" << endl + << "_dynamic_type () const" + << "{" + << "return _static_type ();" + << "}"; + } + } + }; + + // + // + struct Union: Traversal::Union, Context + { + Union (Context& c) + : Context (c) + { + } + + virtual Void + traverse (Type& u) + { + String const& name (ename (u)); + String const& arg (arg_type (u)); + + if (arg == L"void" || poly_code) + { + os << "// " << name << endl + << "//" << endl + << endl; + } + + if (arg == L"void") + { + os << "void " << name << "::" << endl + << "pre ()" + << "{"; + + if (tiein) + { + String const& impl (etiein (u)); + + os << "if (this->" << impl << ")" << endl + << "this->" << impl << "->pre ();"; + } + + os << "}"; + } + + if (poly_code) + { + String id (u.name ()); + + if (String ns = xml_ns_name (u)) + { + id += L' '; + id += ns; + } + + os << "const char* " << name << "::" << endl + << "_static_type ()" + << "{" + << "return " << strlit (id) << ";" + << "}"; + + os << "const char* " << name << "::" << endl + << "_dynamic_type () const" + << "{" + << "return _static_type ();" + << "}"; + } + } + }; + + // + // + struct ParticleReset: Traversal::Element, Context + { + ParticleReset (Context& c) + : Context (c) + { + } + + virtual Void + traverse (SemanticGraph::Element& e) + { + String const& m (emember (e)); + + os << "if (this->" << m << ")" << endl + << "this->" << m << "->_reset ();" + << endl; + + if (poly_code && !anonymous (e.type ())) + { + String const& map (emember_map (e)); + + os << "if (this->" << map << ")" << endl + << "this->" << map << "->reset ();" + << endl; + } + } + }; + + struct AttributeReset: Traversal::Attribute, Context + { + AttributeReset (Context& c) + : Context (c) + { + } + + virtual Void + traverse (Type& a) + { + String const& m (emember (a)); + + os << "if (this->" << m << ")" << endl + << "this->" << m << "->_reset ();" + << endl; + } + }; + + // Complex serialization code. + // + struct Compositor: Traversal::All, + Traversal::Choice, + Traversal::Sequence, + Context + { + Compositor (Context& c) + : Context (c) + { + } + + virtual Void + traverse (SemanticGraph::All& a) + { + // For the all compositor, maxOccurs=1 and minOccurs={0,1}. + // + UnsignedLong min (a.min ()); + + if (min == 0) + os << "if (this->" << epresent (a) << " ())" + << "{"; + + Traversal::All::traverse (a); + + if (min == 0) + { + os << "}"; + + if (!exceptions) + { + os << "if (ctx.error_type ())" << endl + << "return;" + << endl; + } + } + } + + virtual Void + traverse (SemanticGraph::Choice& c) + { + if (c.contains_begin () != c.contains_end ()) + { + UnsignedLong min (c.min ()), max (c.max ()); + + if (min == 0 && max == 1) + { + os << "if (this->" << epresent (c) << " ())" + << "{"; + } + else if (max != 1) + { + os << "while (this->" << enext (c) << " ())" + << "{"; + } + else if (!exceptions) + { + os << "{"; + } + + if (exceptions) + os << "switch (this->" << earm (c) << " ())"; + else + os << earm_tag (c) << " t = this->" << earm (c) << " ();" + << endl + << "if (ctx.error_type ())" << endl + << "return;" + << endl + << "switch (t)"; + + + os << "{"; + + for (SemanticGraph::Choice::ContainsIterator + i (c.contains_begin ()); i != c.contains_end (); ++i) + { + os << "case " << etag (i->particle ()) << ":" + << "{"; + + edge_traverser ().dispatch (*i); + + os << "break;" + << "}"; + } + + // In case of restriction we may not handle all enumerators + // in which case default will help avoid warnings. + // + os << "default:" + << "{" + << "break;" + << "}" + << "}"; // switch + + if (min == 0 || max != 1) + { + os << "}"; + + if (!exceptions) + { + os << "if (ctx.error_type ())" << endl + << "return;" + << endl; + } + } + else if (!exceptions) + { + os << "}"; + } + } + } + + virtual Void + traverse (SemanticGraph::Sequence& s) + { + UnsignedLong min (s.min ()), max (s.max ()); + + if (min == 0 && max == 1) + { + os << "if (this->" << epresent (s) << " ())" + << "{"; + } + else if (max != 1) + { + os << "while (this->" << enext (s) << " ())" + << "{"; + } + + Traversal::Sequence::traverse (s); + + + if (min == 0 || max != 1) + { + os << "}"; + + if (!exceptions) + { + os << "if (ctx.error_type ())" << endl + << "return;" + << endl; + } + } + } + }; + + struct Particle: Traversal::Element, + Traversal::Any, + Context + { + Particle (Context& c) + : Context (c) + { + } + + virtual Void + traverse (SemanticGraph::Element& e) + { + UnsignedLong min (e.min ()), max (e.max ()); + + String const& name (ename (e)); + + os << "// " << name << endl + << "//" << endl; + + if (min == 0 && max == 1) + { + os << "if (this->" << epresent (e) << " ())"; + } + else if (max != 1) + { + os << "while (this->" << enext (e) << " ())"; + } + + os << "{"; + + String const& ret (ret_type (e.type ())); + String const& arg (arg_type (e.type ())); + String fq_type (fq_name (e.type ())); + + Boolean poly (poly_code && !anonymous (e.type ())); + String inst (poly ? String (L"s") : L"this->" + emember (e)); + + if (poly) + os << "ctx.type_id (0);"; + + if (ret == L"void") + os << "this->" << name << " ();" + << endl; + else + os << arg << " r = this->" << name << " ();" + << endl; + + if (!exceptions) + os << "if (ctx.error_type ())" << endl + << "return;" + << endl; + + if (poly) + { + // In case of mixin we use virtual inheritance and only + // dynamic_cast can be used. + // + String cast (mixin ? L"dynamic_cast" : L"static_cast"); + + os << "const void* t = ctx.type_id ();" + << fq_type << "* " << inst << " = 0;" + << endl + << "if (t == 0 && this->" << emember (e) << " != 0)" << endl + << inst << " = this->" << emember (e) << ";" + << "else if (this->" << emember_map (e) << " != 0)" << endl + << inst << " = " << cast << "< " << fq_type << "* > (" << endl + << "this->" << emember_map (e) << "->find (t));" + << endl; + } + + os << "if (" << inst << ")" + << "{"; + + if (exceptions) + { + if (ret == L"void") + os << inst << "->pre ();"; + else + os << inst << "->pre (r);"; + + if (poly) + { + os << endl + << "const char* dt = 0;" + << "if (t != 0)" + << "{" + << "dt = " << inst << "->_dynamic_type ();" + << "if (strcmp (dt, " << fq_type << + "::_static_type ()) == 0)" << endl + << "dt = 0;" + << "}"; + } + + // Only a globally-defined element can be a subst-group root. + // + if (poly && e.global ()) + { + if (e.qualified () && e.namespace_ ().name ()) + os << "const char* ns = " << + strlit (e.namespace_ ().name ()) << ";"; + else + os << "const char* ns = 0;"; + + os << "const char* n = " << strlit (e.name ()) << ";" + << endl; + + os << "if (dt != 0 && " << + "::xsde::cxx::serializer::substitution_map_instance ()" << + ".check (ns, n, dt))" << endl + << "dt = 0;" + << endl; + + os << "if (ns != 0)" << endl + << "this->_start_element (ns, n);" + << "else" << endl + << "this->_start_element (n);"; + } + else + { + if (e.qualified () && e.namespace_ ().name ()) + os << "this->_start_element (" << + strlit (e.namespace_ ().name ()) << ", " << + strlit (e.name ()) << ");"; + else + os << "this->_start_element (" << strlit (e.name ()) << ");"; + } + + if (poly) + { + // Set xsi:type if necessary. + // + os << endl + << "if (dt != 0)" << endl + << "this->_set_type (dt);" + << endl; + } + + os << inst << "->_pre_impl (ctx);" + << inst << "->_serialize_attributes ();" + << inst << "->_serialize_content ();" + << inst << "->_post_impl ();" + << "this->_end_element ();" + << inst << "->post ();"; + } + else + { + if (ret == L"void") + os << inst << "->pre ();"; + else + os << inst << "->pre (r);"; + + // Note that after pre() we need to check both the serializer + // and context error states because of the recursive parsing. + // + os << endl + << "if (" << inst << "->_error_type ())" << endl + << inst << "->_copy_error (ctx);" + << endl; + + os << "if (ctx.error_type ())" << endl + << "return;" + << endl; + + if (poly) + { + os << "const char* dt = 0;" + << "if (t != 0)" + << "{" + << "dt = " << inst << "->_dynamic_type ();" + << "if (strcmp (dt, " << fq_type << + "::_static_type ()) == 0)" << endl + << "dt = 0;" + << "}"; + } + + // Only a globally-defined element can be a subst-group root. + // + if (poly && e.global ()) + { + if (e.qualified () && e.namespace_ ().name ()) + os << "const char* ns = " << + strlit (e.namespace_ ().name ()) << ";"; + else + os << "const char* ns = 0;"; + + os << "const char* n = " << strlit (e.name ()) << ";" + << endl; + + os << "if (dt != 0 && " << + "::xsde::cxx::serializer::substitution_map_instance ()" << + ".check (ns, n, dt))" << endl + << "dt = 0;" + << endl; + + os << "if (ns != 0)" + << "{" + << "if (!this->_start_element (ns, n))" << endl + << "return;" + << "}" + << "else" + << "{" + << "if (!this->_start_element (n))" << endl + << "return;" + << "}"; + } + else + { + if (e.qualified () && e.namespace_ ().name ()) + os << "if (!this->_start_element (" << + strlit (e.namespace_ ().name ()) << ", " << + strlit (e.name ()) << "))" << endl + << "return;" + << endl; + else + os << "if (!this->_start_element (" << + strlit (e.name ()) << "))" << endl + << "return;" + << endl; + } + + if (poly) + { + // Set xsi:type if necessary. + // + os << "if (dt != 0)" + << "{" + << "if (!this->_set_type (dt))" << endl + << "return;" + << "}"; + } + + os << inst << "->_pre_impl (ctx);"; + + os << endl + << "if (ctx.error_type ())" << endl + << "return;" + << endl; + + os << inst << "->_serialize_attributes ();"; + + os << endl + << "if (ctx.error_type ())" << endl + << "return;" + << endl; + + os << inst << "->_serialize_content ();"; + + os << endl + << "if (ctx.error_type ())" << endl + << "return;" + << endl; + + os << inst << "->_post_impl ();"; + + os << endl + << "if (ctx.error_type ())" << endl + << "return;" + << endl; + + os << "if (!this->_end_element ())" << endl + << "return;" + << endl; + + os << inst << "->post ();"; + + // Note that after post() we need to check both the serializer + // and context error states because of the recursive parsing. + // + os << endl + << "if (" << inst << "->_error_type ())" << endl + << inst << "->_copy_error (ctx);" + << endl; + + os << "if (ctx.error_type ())" << endl + << "return;"; + } + + os << "}" // if (inst) + << "}"; + + if ((min == 0 || max != 1) && !exceptions) + { + os << "if (ctx.error_type ())" << endl + << "return;" + << endl; + } + } + + virtual Void + traverse (SemanticGraph::Any& a) + { + UnsignedLong min (a.min ()), max (a.max ()); + + if (min == 0 && max == 1) + { + os << "if (this->" << epresent (a) << " ())"; + + } + else if (max != 1) + { + os << "while (this->" << enext (a) << " ())"; + } + + os << "{"; + + if (stl) + { + os << "::std::string ns, name;"; + + if (exceptions) + { + os << "this->" << ename (a) << " (ns, name);" + << endl + << "if (ns.empty ())" << endl + << "this->_start_element (name.c_str ());" + << "else" << endl + << "this->_start_element (ns.c_str (), name.c_str ());" + << endl + << "this->" << eserialize (a) << " ();" + << "this->_end_element ();"; + } + else + { + os << "this->" << ename (a) << " (ns, name);" + << endl + << "if (ctx.error_type ())" << endl + << "return;" + << endl + << "if (ns.empty ())" + << "{" + << "if (!this->_start_element (name.c_str ()))" << endl + << "return;" + << "}" + << "else" + << "{" + << "if (!this->_start_element (ns.c_str (), " << + "name.c_str ()))" << endl + << "return;" + << "}" + << "this->" << eserialize (a) << " ();" + << endl + << "if (ctx.error_type ())" << endl + << "return;" + << endl + << "if (!this->_end_element ())" << endl + << "return;"; + } + } + else + { + os << "const char* ns = 0;" + << "const char* name;" + << "bool free;"; + + if (exceptions) + { + os << "this->" << ename (a) << " (ns, name, free);" + << endl + << "::xsde::cxx::string auto_ns, auto_name;" + << "if (free)" + << "{" + << "auto_ns.attach (const_cast< char* > (ns));" + << "auto_name.attach (const_cast< char* > (name));" + << "}" + << "if (ns == 0 || *ns == '\\0')" << endl + << "this->_start_element (name);" + << "else" << endl + << "this->_start_element (ns, name);" + << endl + << "this->" << eserialize (a) << " ();" + << "this->_end_element ();"; + } + else + { + os << "this->" << ename (a) << " (ns, name, free);" + << endl + << "if (ctx.error_type ())" << endl + << "return;" + << endl + << "bool r;" + << "if (ns == 0 || *ns == '\\0')" << endl + << "r = this->_start_element (name);" + << "else" << endl + << "r = this->_start_element (ns, name);" + << endl + << "if (free)" + << "{" + << "delete[] ns;" + << "delete[] name;" + << "}" + << "if (!r)" << endl + << "return;" + << endl + << "this->" << eserialize (a) << " ();" + << endl + << "if (ctx.error_type ())" << endl + << "return;" + << endl + << "if (!this->_end_element ())" << endl + << "return;"; + } + } + + os << "}"; + + if (!exceptions && (min == 0 || max != 1)) + { + os << "if (ctx.error_type ())" << endl + << "return;" + << endl; + } + } + + }; + + struct Attribute: Traversal::Attribute, + Traversal::AnyAttribute, + Context + { + Attribute (Context& c) + : Context (c) + { + } + + virtual Void + traverse (SemanticGraph::Attribute& a) + { + String const& name (ename (a)); + + os << "// " << name << endl + << "//" << endl; + + if (a.optional ()) + { + os << "if (this->" << epresent (a) << " ())"; + } + + os << "{"; + + String const& inst (emember (a)); + String const& ret (ret_type (a.type ())); + String const& arg (arg_type (a.type ())); + + if (ret == L"void") + os << "this->" << name << " ();" + << endl; + else + os << arg << " r = this->" << name << " ();" + << endl; + + if (!exceptions) + os << "if (ctx.error_type ())" << endl + << "return;" + << endl; + + os << "if (this->" << inst << ")" + << "{"; + + if (exceptions) + { + if (ret == L"void") + os << "this->" << inst << "->pre ();"; + else + os << "this->" << inst << "->pre (r);"; + + if (a.qualified () && a.namespace_ ().name ()) + os << "this->_start_attribute (" << + strlit (a.namespace_ ().name ()) << ", " << + strlit (a.name ()) << ");"; + else + os << "this->_start_attribute (" << strlit (a.name ()) << ");"; + + os << "this->" << inst << "->_pre_impl (ctx);" + << "this->" << inst << "->_serialize_content ();" + << "this->" << inst << "->_post_impl ();" + << "this->_end_attribute ();" + << "this->" << inst << "->post ();"; + } + else + { + if (ret == L"void") + os << "this->" << inst << "->pre ();"; + else + os << "this->" << inst << "->pre (r);"; + + os << endl + << "if (this->" << inst << "->_error_type ())" << endl + << "this->" << inst << "->_copy_error (ctx);" + << endl; + + os << "if (ctx.error_type ())" << endl + << "return;" + << endl; + + if (a.qualified () && a.namespace_ ().name ()) + os << "if (!this->_start_attribute (" << + strlit (a.namespace_ ().name ()) << ", " << + strlit (a.name ()) << "))" << endl + << "return;" + << endl; + else + os << "if (!this->_start_attribute (" << + strlit (a.name ()) << "))" << endl + << "return;" + << endl; + + os << "this->" << inst << "->_pre_impl (ctx);"; + + os << endl + << "if (ctx.error_type ())" << endl + << "return;" + << endl; + + os << "this->" << inst << "->_serialize_content ();"; + + os << endl + << "if (ctx.error_type ())" << endl + << "return;" + << endl; + + os << "this->" << inst << "->_post_impl ();"; + + os << endl + << "if (ctx.error_type ())" << endl + << "return;" + << endl; + + os << "if (!this->_end_attribute ())" << endl + << "return;" + << endl; + + os << "this->" << inst << "->post ();"; + + os << endl + << "if (this->" << inst << "->_error_type ())" << endl + << "this->" << inst << "->_copy_error (ctx);" + << endl; + + os << "if (ctx.error_type ())" << endl + << "return;"; + } + + os << "}" // if (inst) + << "}"; + + if (a.optional () && !exceptions) + { + os << "if (ctx.error_type ())" << endl + << "return;" + << endl; + } + } + + virtual Void + traverse (SemanticGraph::AnyAttribute& a) + { + os << "while (this->" << enext (a) << " ())" + << "{"; + + if (stl) + { + os << "::std::string ns, name;"; + + if (exceptions) + { + os << "this->" << ename (a) << " (ns, name);" + << endl + << "if (ns.empty ())" << endl + << "this->_start_attribute (name.c_str ());" + << "else" << endl + << "this->_start_attribute (ns.c_str (), name.c_str ());" + << endl + << "this->" << eserialize (a) << " ();" + << "this->_end_attribute ();"; + } + else + { + os << "this->" << ename (a) << " (ns, name);" + << endl + << "if (ctx.error_type ())" << endl + << "return;" + << endl + << "if (ns.empty ())" + << "{" + << "if (!this->_start_attribute (name.c_str ()))" << endl + << "return;" + << "}" + << "else" + << "{" + << "if (!this->_start_attribute (ns.c_str (), " << + "name.c_str ()))" << endl + << "return;" + << "}" + << "this->" << eserialize (a) << " ();" + << endl + << "if (ctx.error_type ())" << endl + << "return;" + << endl + << "if (!this->_end_attribute ())" << endl + << "return;"; + } + } + else + { + os << "const char* ns = 0;" + << "const char* name;" + << "bool free;"; + + if (exceptions) + { + os << "this->" << ename (a) << " (ns, name, free);" + << endl + << "::xsde::cxx::string auto_ns, auto_name;" + << "if (free)" + << "{" + << "auto_ns.attach (const_cast< char* > (ns));" + << "auto_name.attach (const_cast< char* > (name));" + << "}" + << "if (ns == 0 || *ns == '\\0')" << endl + << "this->_start_attribute (name);" + << "else" << endl + << "this->_start_attribute (ns, name);" + << endl + << "this->" << eserialize (a) << " ();" + << "this->_end_attribute ();"; + } + else + { + os << "this->" << ename (a) << " (ns, name, free);" + << endl + << "if (ctx.error_type ())" << endl + << "return;" + << endl + << "bool r;" + << "if (ns == 0 || *ns == '\\0')" << endl + << "r = this->_start_attribute (name);" + << "else" << endl + << "r = this->_start_attribute (ns, name);" + << endl + << "if (free)" + << "{" + << "delete[] ns;" + << "delete[] name;" + << "}" + << "if (!r)" << endl + << "return;" + << endl + << "this->" << eserialize (a) << " ();" + << endl + << "if (ctx.error_type ())" << endl + << "return;" + << endl + << "if (!this->_end_attribute ())" << endl + << "return;"; + } + } + + os << "}"; + + if (!exceptions) + { + os << "if (ctx.error_type ())" << endl + << "return;" + << endl; + } + } + }; + + // Callbacks. + // + struct CompositorCallback: Traversal::All, + Traversal::Choice, + Traversal::Sequence, + Context + { + CompositorCallback (Context& c) + : Context (c) + { + } + + virtual Void + traverse (SemanticGraph::All& a) + { + if (!a.context ().count ("xsd-frontend-restriction-correspondence")) + { + // For the all compositor, maxOccurs=1 and minOccurs={0,1}. + // + if (a.min () == 0) + { + SemanticGraph::Scope& s (scope (a)); + String const& present (epresent (a)); + + os << "bool " << ename (s) << "::" << endl + << present << " ()" + << "{"; + + if (tiein) + { + String const& impl ( + etiein (dynamic_cast<SemanticGraph::Type&> (s))); + + os << "return this->" << impl << " ? this->" << impl << + "->" << present << " () : false;"; + } + else + os << "return false;"; + + os << "}"; + } + } + + Traversal::All::traverse (a); + } + + virtual Void + traverse (SemanticGraph::Choice& c) + { + if (SemanticGraph::Compositor* b = correspondent (c)) + { + UnsignedLong smin (c.min ()); + UnsignedLong bmax (b->max ()); + + if (bmax != 1 && smin == 0) + { + String const& next (enext (c)); + String const& present (epresent (c)); + + SemanticGraph::Scope& scope (this->scope (c)); + + os << "bool " << ename (scope) << "::" << endl + << present << " ()" + << "{"; + + if (tiein) + { + String const& impl ( + etiein (dynamic_cast<SemanticGraph::Type&> (scope))); + + os << "return this->" << impl << " ? this->" << impl << + "->" << present << " () : this->" << next << " ();"; + } + else + os << "return this->" << next << " ();"; + + os << "}"; + } + } + else + { + UnsignedLong min (c.min ()), max (c.max ()); + + if (min == 0) + { + SemanticGraph::Scope& scope (this->scope (c)); + String const& s (ename (scope)); + + String impl; + + if (tiein) + impl = etiein (dynamic_cast<SemanticGraph::Type&> (scope)); + + if (max == 1) + { + String const& present (epresent (c)); + + os << "bool " << s << "::" << endl + << present << " ()" + << "{"; + + if (tiein) + os << "return this->" << impl << " ? this->" << impl << + "->" << present << " () : false;"; + else + os << "return false;"; + + os << "}"; + } + else + { + String const& next (enext (c)); + + os << "bool " << s << "::" << endl + << next << " ()" + << "{"; + + if (tiein) + os << "return this->" << impl << " ? this->" << impl << + "->" << next << " () : false;"; + else + os << "return false;"; + + os << "}"; + } + + String const& arm (earm (c)); + String const& tag (etag (c.contains_begin ()->particle ())); + + os << s << "::" << earm_tag (c) << " " << s << "::" << endl + << arm << " ()" + << "{"; + + if (tiein) + os << "return this->" << impl << " ? this->" << impl << + "->" << arm << " () : " << tag << ";"; + else + os << "return " << tag << ";"; + + os << "}"; + } + } + + Traversal::Choice::traverse (c); + } + + virtual Void + traverse (SemanticGraph::Sequence& s) + { + if (SemanticGraph::Compositor* b = correspondent (s)) + { + UnsignedLong smin (s.min ()); + UnsignedLong bmax (b->max ()); + + if (bmax != 1 && smin == 0) + { + String const& next (enext (s)); + String const& present (epresent (s)); + + SemanticGraph::Scope& scope (this->scope (s)); + + os << "bool " << ename (scope) << "::" << endl + << present << " ()" + << "{"; + + if (tiein) + { + String const& impl ( + etiein (dynamic_cast<SemanticGraph::Type&> (scope))); + + os << "return this->" << impl << " ? this->" << impl << + "->" << present << " () : this->" << next << " ();"; + } + else + os << "return this->" << next << " ();"; + + os << "}"; + } + } + else + { + UnsignedLong min (s.min ()), max (s.max ()); + + if (min == 0) + { + SemanticGraph::Scope& scope (this->scope (s)); + + String impl; + + if (tiein) + impl = etiein (dynamic_cast<SemanticGraph::Type&> (scope)); + + if (max == 1) + { + String const& present (epresent (s)); + + os << "bool " << ename (scope) << "::" << endl + << present << " ()" + << "{"; + + if (tiein) + os << "return this->" << impl << " ? this->" << impl << + "->" << present << " () : false;"; + else + os << "return false;"; + + os << "}"; + } + else + { + String const& next (enext (s)); + + os << "bool " << ename (scope) << "::" << endl + << next << " ()" + << "{"; + + if (tiein) + os << "return this->" << impl << " ? this->" << impl << + "->" << next << " () : false;"; + else + os << "return false;"; + + os << "}"; + } + } + } + + Traversal::Sequence::traverse (s); + } + + private: + SemanticGraph::Scope& + scope (SemanticGraph::Compositor& c) + { + SemanticGraph::Compositor* root (&c); + + while (root->contained_particle_p ()) + root = &root->contained_particle ().compositor (); + + return dynamic_cast<SemanticGraph::Scope&> ( + root->contained_compositor ().container ()); + } + }; + + struct ParticleCallback: Traversal::Element, + Traversal::Any, + Context + { + ParticleCallback (Context& c) + : Context (c) + { + } + + virtual Void + traverse (SemanticGraph::Element& e) + { + if (SemanticGraph::Element* b = correspondent (e)) + { + if (b->max () != 1 && e.min () == 0) + { + String const& next (enext (e)); + String const& present (epresent (e)); + + os << "bool " << ename (e.scope ()) << "::" << endl + << present << " ()" + << "{"; + + if (tiein) + { + String const& impl ( + etiein (dynamic_cast<SemanticGraph::Type&> (e.scope ()))); + + os << "return this->" << impl << " ? this->" << impl << + "->" << present << " () : this->" << next << " ();"; + } + else + os << "return this->" << next << " ();"; + + os << "}"; + } + } + else + { + UnsignedLong min (e.min ()), max (e.max ()); + String const& s (ename (e.scope ())); + + String impl; + + if (tiein) + impl = etiein (dynamic_cast<SemanticGraph::Type&> (e.scope ())); + + if (min == 0) + { + if (max == 1) + { + String const& present (epresent (e)); + + os << "bool " << s << "::" << endl + << present << " ()" + << "{"; + + if (tiein) + os << "return this->" << impl << " ? this->" << impl << + "->" << present << " () : false;"; + else + os << "return false;"; + + os << "}"; + } + else + { + String const& next (enext (e)); + + os << "bool " << s << "::" << endl + << next << " ()" + << "{"; + + if (tiein) + os << "return this->" << impl << " ? this->" << impl << + "->" << next << " () : false;"; + else + os << "return false;"; + + os << "}"; + } + } + + // The callback is non-pure-virtual only if the return type + // is void. + // + if (ret_type (e.type ()) == L"void") + { + String const& name (ename (e)); + + os << "void " << s << "::" << endl + << name << " ()" + << "{"; + + if (tiein) + os << "if (this->" << impl << ")" << endl + << "this->" << impl << "->" << name << " ();"; + + os << "}"; + } + } + } + + virtual Void + traverse (SemanticGraph::Any& a) + { + if (SemanticGraph::Any* b = correspondent (a)) + { + if (b->max () != 1 && a.min () == 0) + { + String const& next (enext (a)); + String const& present (epresent (a)); + + os << "bool " << ename (a.scope ()) << "::" << endl + << present << " ()" + << "{"; + + if (tiein) + { + String const& impl ( + etiein (dynamic_cast<SemanticGraph::Type&> (a.scope ()))); + + os << "return this->" << impl << " ? this->" << impl << + "->" << present << " () : this->" << next << " ();"; + } + else + os << "return this->" << next << " ();"; + + os << "}"; + } + } + else + { + UnsignedLong min (a.min ()), max (a.max ()); + + if (min == 0 || + a.contained_particle ().compositor ().is_a< + SemanticGraph::Choice> ()) + { + String const& s (ename (a.scope ())); + String impl; + + if (tiein) + impl = etiein (dynamic_cast<SemanticGraph::Type&> (a.scope ())); + + if (min == 0 && max == 1) + { + String const& present (epresent (a)); + + os << "bool " << s << "::" << endl + << present << " ()" + << "{"; + + if (tiein) + os << "return this->" << impl << " ? this->" << impl << + "->" << present << " () : false;"; + else + os << "return false;"; + + os << "}"; + } + else if (max != 1) + { + String const& next (enext (a)); + + os << "bool " << s << "::" << endl + << next << " ()" + << "{"; + + if (tiein) + os << "return this->" << impl << " ? this->" << impl << + "->" << next << " () : false;"; + else + os << "return false;"; + + os << "}"; + } + + String const& name (ename (a)); + + if (stl) + { + if (tiein) + os << "void " << s << "::" << endl + << name << " (::std::string& ns, ::std::string& n)" + << "{" + << "if (this->" << impl << ")" << endl + << "this->" << impl << "->" << name << " (ns, n);" + << "}"; + + else + os << "void " << s << "::" << endl + << name << " (::std::string&, ::std::string&)" + << "{" + << "}"; + } + else + { + if (tiein) + os << "void " << s << "::" << endl + << name << " (const char*& ns, const char*& n, bool& f)" + << "{" + << "if (this->" << impl << ")" << endl + << "this->" << impl << "->" << name << " (ns, n, f);" + << "}"; + else + os << "void " << s << "::" << endl + << name << " (const char*&, const char*&, bool&)" + << "{" + << "}"; + } + + String const& serialize (eserialize (a)); + + os << "void " << s << "::" << endl + << serialize << " ()" + << "{"; + + if (tiein) + os << "if (this->" << impl << ")" << endl + << "this->" << impl << "->" << serialize << " ();"; + + os << "}"; + } + } + + } + }; + + struct AttributeCallback: Traversal::Attribute, + Traversal::AnyAttribute, + Context + { + AttributeCallback (Context& c) + : Context (c) + { + } + + virtual Void + traverse (SemanticGraph::Attribute& a) + { + String const& s (ename (a.scope ())); + + String impl; + + if (tiein) + impl = etiein (dynamic_cast<SemanticGraph::Type&> (a.scope ())); + + if (a.optional ()) + { + String const& present (epresent (a)); + + os << "bool " << s << "::" << endl + << present << " ()" + << "{"; + + if (tiein) + os << "return this->" << impl << " ? this->" << impl << + "->" << present << " () : false;"; + else + os << "return false;"; + + os << "}"; + } + + // The callback is non-pure-virtual only if the return type + // is void. + // + if (ret_type (a.type ()) == L"void") + { + String const& name (ename (a)); + + os << "void " << s << "::" << endl + << name << " ()" + << "{"; + + if (tiein) + os << "if (this->" << impl << ")" << endl + << "this->" << impl << "->" << name << " ();"; + + os << "}"; + } + } + + virtual Void + traverse (SemanticGraph::AnyAttribute& a) + { + String const& s (ename (a.scope ())); + + String impl; + + if (tiein) + impl = etiein (dynamic_cast<SemanticGraph::Type&> (a.scope ())); + + String const& next (enext (a)); + + os << "bool " << s << "::" << endl + << next << " ()" + << "{"; + + if (tiein) + os << "return this->" << impl << " ? this->" << impl << + "->" << next << " () : false;"; + else + os << "return false;"; + + os << "}"; + + String const& name (ename (a)); + + if (stl) + { + if (tiein) + os << "void " << s << "::" << endl + << name << " (::std::string& ns, ::std::string& n)" + << "{" + << "if (this->" << impl << ")" << endl + << "this->" << impl << "->" << name << " (ns, n);" + << "}"; + + else + os << "void " << s << "::" << endl + << name << " (::std::string&, ::std::string&)" + << "{" + << "}"; + } + else + { + if (tiein) + os << "void " << s << "::" << endl + << name << " (const char*& ns, const char*& n, bool& f)" + << "{" + << "if (this->" << impl << ")" << endl + << "this->" << impl << "->" << name << " (ns, n, f);" + << "}"; + else + os << "void " << s << "::" << endl + << name << " (const char*&, const char*&, bool&)" + << "{" + << "}"; + } + + String const& serialize (eserialize (a)); + + os << "void " << s << "::" << endl + << serialize << " ()" + << "{"; + + if (tiein) + os << "if (this->" << impl << ")" << endl + << "this->" << impl << "->" << serialize << " ();"; + + os << "}"; + } + }; + + // + // + struct Complex : Traversal::Complex, Context + { + Complex (Context& c) + : Context (c), + compositor_callback_ (c), + particle_callback_ (c), + attribute_callback_ (c), + particle_reset_ (c), + attribute_reset_ (c), + compositor_ (c), + particle_ (c), + attribute_ (c) + { + // Callback. + // + contains_compositor_callback_ >> compositor_callback_; + compositor_callback_ >> contains_particle_callback_; + contains_particle_callback_ >> compositor_callback_; + contains_particle_callback_ >> particle_callback_; + + names_attribute_callback_ >> attribute_callback_; + + // Reset. + // + contains_compositor_reset_ >> compositor_reset_; + compositor_reset_ >> contains_particle_reset_; + contains_particle_reset_ >> compositor_reset_; + contains_particle_reset_ >> particle_reset_; + + names_attribute_reset_ >> attribute_reset_; + + // Serialization code. + // + contains_compositor_ >> compositor_; + compositor_ >> contains_particle_; + contains_particle_ >> compositor_; + contains_particle_ >> particle_; + + names_attribute_ >> attribute_; + } + + virtual Void + traverse (Type& c) + { + Boolean hb (c.inherits_p ()); + Boolean he (has<Traversal::Element> (c)); + Boolean ha (has<Traversal::Attribute> (c)); + + Boolean hae (has_particle<Traversal::Any> (c)); + Boolean haa (has<Traversal::AnyAttribute> (c)); + + String const& arg (arg_type (c)); + Boolean same (hb && arg == arg_type (c.inherits ().base ())); + + String const& name (ename (c)); + + os << "// " << name << endl + << "//" << endl + << endl; + + // pre + // + if (!same && arg == L"void") + { + os << "void " << name << "::" << endl + << "pre ()" + << "{"; + + if (tiein) + { + String const& impl (etiein (c)); + + os << "if (this->" << impl << ")" << endl + << "this->" << impl << "->pre ();"; + } + + os << "}"; + } + + // Member callbacks. + // + if (!restriction_p (c)) + { + if (ha || haa) + names (c, names_attribute_callback_); + } + + if (he || hae) + contains_compositor (c, contains_compositor_callback_); + + // reset + // + if (!restriction_p (c) && (he || ha) && reset) + { + os << "void " << name << "::" << endl + << "_reset ()" + << "{"; + + // Avoid recursion in case of recursive parsing. + // + if (he) + os << "if (this->resetting_)" << endl + << "return;" + << endl; + + // Reset the base. We cannot use the fully-qualified base name + // directly because of some broken compilers (EVC 4.0). + // + String base (unclash (name, "base")); + + os << "typedef "; + + if (hb) + os << fq_name (c.inherits ().base ()); + else + os << complex_base; + + os << " " << base << ";" + << base << "::_reset ();" + << endl; + + // Reset member serializer. + // + + if (ha) + names (c, names_attribute_reset_); + + if (he) + { + os << "this->resetting_ = true;" + << endl; + + contains_compositor (c, contains_compositor_reset_); + + os << "this->resetting_ = false;" + << endl; + } + + os << "}"; + } + + // + // + if (poly_code) + { + String id (c.name ()); + + if (String ns = xml_ns_name (c)) + { + id += L' '; + id += ns; + } + + os << "const char* " << name << "::" << endl + << "_static_type ()" + << "{" + << "return " << strlit (id) << ";" + << "}"; + + os << "const char* " << name << "::" << endl + << "_dynamic_type () const" + << "{" + << "return _static_type ();" + << "}"; + + if (hb && validation) + { + Boolean gen (!anonymous (c)); + + // We normally don't need to enter anonymous types into + // the inheritance map. The only exception is when an + // anonymous types is defined inside an element that + // is a member of a substitution group. + // + if (!gen) + { + // The first instance that this anonymous type classifies + // is the prototype for others if any. + // + SemanticGraph::Instance& i ( + c.classifies_begin ()->instance ()); + + if (SemanticGraph::Element* e = + dynamic_cast<SemanticGraph::Element*> (&i)) + { + if (e->substitutes_p ()) + gen = true; + } + } + + if (gen) + { + SemanticGraph::Type& base (c.inherits ().base ()); + + os << "static" << endl + << "const ::xsde::cxx::serializer::validating::" << + "inheritance_map_entry" << endl + << "_xsde_" << name << "_inheritance_map_entry_ (" << endl + << name << "::_static_type ()," << endl + << fq_name (base) << "::_static_type ());" + << endl; + } + } + } + + if (tiein && hb) + { + // If our base has pure virtual functions, override them here. + // + BaseOverride t (*this, name); + t.dispatch (c.inherits ().base ()); + } + + // If we are validating, the rest is generated elsewere. + // + if (validation) + return; + + // Don't use restriction_p here since we don't want special + // treatment of anyType. + // + Boolean restriction ( + hb && c.inherits ().is_a<SemanticGraph::Restricts> ()); + + // _serialize_attributes + // + if (ha || haa) + { + os << "void " << name << "::" << endl + << "_serialize_attributes ()" + << "{"; + + // We need context for wildcards only if we are using error + // codes. + // + if (ha || !exceptions) + os << "::xsde::cxx::serializer::context& ctx = this->_context ();" + << endl; + + if (hb && !restriction) + { + // We cannot use the fully-qualified base name directly + // because of some broken compilers (EVC 4.0). + // + String base (unclash (name, "base")); + + os << "typedef " << fq_name (c.inherits ().base ()) << " " << + base << ";" + << base << "::_serialize_attributes ();" + << endl; + + if (!exceptions) + { + os << "if (ctx.error_type ())" << endl + << "return;" + << endl; + } + } + + names (c, names_attribute_); + + os << "}"; + } + + // _serialize_content + // + if (he || hae) + { + os << "void " << name << "::" << endl + << "_serialize_content ()" + << "{"; + + // We need context for wildcards only if we are using error + // codes. + // + if (he || !exceptions) + os << "::xsde::cxx::serializer::context& ctx = this->_context ();" + << endl; + + if (hb && !restriction) + { + // We cannot use the fully-qualified base name directly + // because of some broken compilers (EVC 4.0). + // + String base (unclash (name, "base")); + + os << "typedef " << fq_name (c.inherits ().base ()) << " " << + base << ";" + << base << "::_serialize_content ();" + << endl; + + if (!exceptions) + { + os << "if (ctx.error_type ())" << endl + << "return;" + << endl; + } + } + + contains_compositor (c, contains_compositor_); + + os << "}"; + } + } + + private: + // + // + CompositorCallback compositor_callback_; + ParticleCallback particle_callback_; + Traversal::ContainsCompositor contains_compositor_callback_; + Traversal::ContainsParticle contains_particle_callback_; + + AttributeCallback attribute_callback_; + Traversal::Names names_attribute_callback_; + + // + // + Traversal::Compositor compositor_reset_; + ParticleReset particle_reset_; + Traversal::ContainsCompositor contains_compositor_reset_; + Traversal::ContainsParticle contains_particle_reset_; + + AttributeReset attribute_reset_; + Traversal::Names names_attribute_reset_; + + // + // + Compositor compositor_; + Particle particle_; + Traversal::ContainsCompositor contains_compositor_; + Traversal::ContainsParticle contains_particle_; + + Attribute attribute_; + Traversal::Names names_attribute_; + }; + + + // Generate substitution group map entries. + // + struct GlobalElement: Traversal::Element, Context + { + GlobalElement (Context& c) + : Context (c) + { + } + + virtual Void + traverse (Type& e) + { + if (e.substitutes_p ()) + { + String name (escape (e.name ())); + Type& r (e.substitutes ().root ()); + + SemanticGraph::Type& type (e.type ()); + + String r_id (r.name ()); + + if (String const& ns = r.namespace_ ().name ()) + { + r_id += L' '; + r_id += ns; + } + + os << "// Substitution map entry for " << comment (e.name ()) << + "." << endl + << "//" << endl + << "static" << endl + << "const ::xsde::cxx::serializer::substitution_map_entry" << endl + << "_xsde_" << name << "_substitution_map_entry_ (" << endl + << strlit (r_id) << "," << endl; + + if (String const& ns = e.namespace_ ().name ()) + os << strlit (ns) << "," << endl; + else + os << "0," << endl; + + os << strlit (e.name ()) << "," << endl + << fq_name (type) << "::_static_type ());" + << endl; + } + } + }; + } + + Void + generate_serializer_source (Context& ctx) + { + if (ctx.tiein) + ctx.os << "#include <assert.h>" << endl + << endl; + + if (ctx.poly_code) + { + ctx.os << "#include <string.h>" << endl + << "#include <xsde/cxx/serializer/substitution-map.hxx>" << endl; + + if (ctx.validation) + ctx.os << "#include <xsde/cxx/serializer/validating/inheritance-map.hxx>" << endl + << endl; + else + ctx.os << endl; + + ctx.os << "static" << endl + << "const ::xsde::cxx::serializer::substitution_map_init" << endl + << "_xsde_substitution_map_init_;" + << endl; + + if (ctx.validation) + { + ctx.os << "static" << endl + << "const ::xsde::cxx::serializer::validating::" << + "inheritance_map_init" << endl + << "_xsde_inheritance_map_init_;" + << endl; + } + } + + // Emit "weak" header includes that are used in the file-per-type + // compilation model. + // + if (ctx.options.value<CLI::generate_inline> ()) + { + Traversal::Schema schema; + Includes includes (ctx, Includes::source); + + schema >> includes; + schema.dispatch (ctx.schema_root); + } + + Traversal::Schema schema; + + Traversal::Sources sources; + Traversal::Names schema_names; + + Namespace ns (ctx); + Traversal::Names names; + + schema >> sources >> schema; + schema >> schema_names >> ns >> names; + + List list (ctx); + Union union_ (ctx); + Complex complex (ctx); + Enumeration enumeration (ctx); + GlobalElement global_element (ctx); + + names >> list; + names >> union_; + names >> complex; + names >> enumeration; + + if (ctx.poly_code) + names >> global_element; + + schema.dispatch (ctx.schema_root); + } + } +} |