// file : xsd/cxx/tree/tree-source.cxx // copyright : Copyright (c) 2005-2014 Code Synthesis Tools CC // license : GNU GPL v2 + exceptions; see accompanying LICENSE file #include #include #include #include #include #include using namespace std; namespace CXX { namespace Tree { namespace { struct List: Traversal::List, Context { List (Context& c) : Context (c) { } virtual void traverse (Type& l) { String name (ename (l)); // If renamed name is empty then we do not need to generate // anything for this type. // if (renamed_type (l, name) && !name) return; os << "// " << name << endl << "//" << endl << endl; if (!options.suppress_parsing ()) { SemanticGraph::Type& item_type (l.argumented ().type ()); String base (L"::xsd::cxx::tree::list< " + item_type_name (item_type) + L", " + char_type); if (item_type.is_a ()) base += L", ::xsd::cxx::tree::schema_type::double_"; else if (item_type.is_a ()) base += L", ::xsd::cxx::tree::schema_type::decimal"; base += L" >"; // c-tor (xercesc::DOMElement) // os << name << "::" << endl << name << " (const " << xerces_ns << "::DOMElement& e," << endl << flags_type << " f," << endl << container << "* c)" << endl << ": " << any_simple_type << " (e, f, c)," << endl << " " << base << " (e, f, this)" << "{" << "}"; // c-tor (xercesc::DOMAttr) // os << name << "::" << endl << name << " (const " << xerces_ns << "::DOMAttr& a," << endl << flags_type << " f," << endl << container << "* c)" << endl << ": " << any_simple_type << " (a, f, c)," << endl << " " << base << " (a, f, this)" << "{" << "}"; // c-tor (string const&, xercesc::DOMElement) // os << name << "::" << endl << name << " (const " << string_type << "& s," << endl << "const " << xerces_ns << "::DOMElement* e," << endl << flags_type << " f," << endl << container << "* c)" << endl << ": " << any_simple_type << " (s, e, f, c)," << endl << " " << base << " (s, e, f, this)" << "{" << "}"; } // _clone // os << name << "* " << name << "::" << endl << "_clone (" << flags_type << " f," << endl << container << "* c) const" << "{" << "return new class " << name << " (*this, f, c);" << "}"; // d-tor // os << name << "::" << endl << "~" << name << " ()" << "{" << "}"; // Register with type factory map. // if (polymorphic && polymorphic_p (l)) { // Note that we are using the original type name. // String const& name (ename (l)); // If this type is anonymous but substitutes, then it will // be registered as part of the substitution registration. // if (!anonymous_p (l) && !options.suppress_parsing ()) { os << "static" << endl << "const ::xsd::cxx::tree::type_factory_initializer< " << poly_plate << ", " << char_type << ", " << name << " >" << endl << "_xsd_" << name << "_type_factory_init (" << endl << strlit (l.name ()) << "," << endl << strlit (xml_ns_name (l)) << ");" << endl; } if ((!anonymous_p (l) || anonymous_substitutes_p (l)) && options.generate_comparison ()) { os << "static" << endl << "const ::xsd::cxx::tree::comparison_initializer< " << poly_plate << ", " << char_type << ", " << name << " >" << endl << "_xsd_" << name << "_comparison_init;" << endl; } } } private: String item_type_name (SemanticGraph::Type& t) { std::wostringstream o; MemberTypeName type (*this, o); type.dispatch (t); return o.str (); } }; struct Union: Traversal::Union, Context { Union (Context& c) : Context (c) { } virtual void traverse (Type& u) { String name (ename (u)); // If renamed name is empty then we do not need to generate // anything for this type. // if (renamed_type (u, name) && !name) return; String const& base (xs_string_type); os << "// " << name << endl << "//" << endl << endl; if (!options.suppress_parsing ()) { // c-tor (xercesc::DOMElement) // os << name << "::" << endl << name << " (const " << xerces_ns << "::DOMElement& e," << endl << flags_type << " f," << endl << container << "* c)" << endl << ": " << base << " (e, f, c)" << "{" << "}"; // c-tor (xercesc::DOMAttr) // os << name << "::" << endl << name << " (const " << xerces_ns << "::DOMAttr& a," << endl << flags_type << " f," << endl << container << "* c)" << endl << ": " << base << " (a, f, c)" << "{" << "}"; // c-tor (string const&, xercesc::DOMElement) // os << name << "::" << endl << name << " (const " << string_type << "& s," << endl << "const " << xerces_ns << "::DOMElement* e," << endl << flags_type << " f," << endl << container << "* c)" << endl << ": " << base << " (s, e, f, c)" << "{" << "}"; } // _clone // os << name << "* " << name << "::" << endl << "_clone (" << flags_type << " f," << endl << container << "* c) const" << "{" << "return new class " << name << " (*this, f, c);" << "}"; // Register with type factory map. // if (polymorphic && polymorphic_p (u)) { // Note that we are using the original type name. // String const& name (ename (u)); // If this type is anonymous but substitutes, then it will // be registered as part of the substitution registration. // if (!anonymous_p (u) && !options.suppress_parsing ()) { os << "static" << endl << "const ::xsd::cxx::tree::type_factory_initializer< " << poly_plate << ", " << char_type << ", " << name << " >" << endl << "_xsd_" << name << "_type_factory_init (" << endl << strlit (u.name ()) << "," << endl << strlit (xml_ns_name (u)) << ");" << endl; } if ((!anonymous_p (u) || anonymous_substitutes_p (u)) && options.generate_comparison ()) { os << "static" << endl << "const ::xsd::cxx::tree::comparison_initializer< " << poly_plate << ", " << char_type << ", " << name << " >" << endl << "_xsd_" << name << "_comparison_init;" << endl; } } } }; // Enumeration mapping. // struct EnumeratorLiteral: Traversal::Enumerator, Context { EnumeratorLiteral (Context& c) : Context (c) { } virtual void traverse (Type& e) { os << strlit (e.name ()); } }; // // struct LiteralInfo { LiteralInfo (String const& value, String const& name) : value_ (value), name_ (name) { } String value_; String name_; }; bool operator< (LiteralInfo const& x, LiteralInfo const& y) { return x.value_ < y.value_; } typedef list LiteralInfoList; // Populate LiteralInfoList // struct EnumeratorLiteralInfo: Traversal::Enumerator, Context { EnumeratorLiteralInfo (Context& c, LiteralInfoList& list) : Context (c), list_ (list) { } virtual void traverse (Type& e) { list_.push_back (LiteralInfo (e.name (), ename (e))); } private: LiteralInfoList& list_; }; struct Enumeration: Traversal::Enumeration, Context { Enumeration (Context& c) : Context (c), enumerator_literal_ (c) { names_enumerator_literal_ >> enumerator_literal_; } virtual void traverse (Type& e) { String name (ename (e)); // If renamed name is empty then we do not need to generate // anything for this type. // if (renamed_type (e, name) && !name) return; bool string_based (false); { IsStringBasedType t (string_based); t.dispatch (e); } SemanticGraph::Enumeration* be (0); bool enum_based (false); if (string_based) { IsEnumBasedType t (be); t.dispatch (e); enum_based = (be != 0); } String value; if (string_based) value = evalue (e); size_t enum_count (0); for (Type::NamesIterator i (e.names_begin ()), end (e.names_end ()); i != end; ++i) ++enum_count; String base; // base type name { std::wostringstream o; BaseTypeName base_type (*this, o); Traversal::Inherits inherits_type (base_type); inherits (e, inherits_type); base = o.str (); } os << "// " << name << endl << "//" << endl << endl; if (!options.suppress_parsing ()) { // c-tor (xercesc::DOMElement) // os << name << "::" << endl << name << " (const " << xerces_ns << "::DOMElement& e," << endl << flags_type << " f," << endl << container << "* c)" << endl << ": " << base << " (e, f, c)" << "{"; if (string_based) os << "_xsd_" << name << "_convert ();"; os << "}"; // c-tor (xercesc::DOMAttr) // os << name << "::" << endl << name << " (const " << xerces_ns << "::DOMAttr& a," << endl << flags_type << " f," << endl << container << "* c)" << endl << ": " << base << " (a, f, c)" << "{"; if (string_based) { os << "_xsd_" << name << "_convert ();"; } os << "}"; // c-tor (string const&, xercesc::DOMElement) // os << name << "::" << endl << name << " (const " << string_type << "& s," << endl << "const " << xerces_ns << "::DOMElement* e," << endl << flags_type << " f," << endl << container << "* c)" << endl << ": " << base << " (s, e, f, c)" << "{"; if (string_based) { os << "_xsd_" << name << "_convert ();"; } os << "}"; } // _clone // os << name << "* " << name << "::" << endl << "_clone (" << flags_type << " f," << endl << container << "* c) const" << "{" << "return new class " << name << " (*this, f, c);" << "}"; // convert // // @@ TODO: expected list // if (string_based) { String i_name (L"_xsd_" + name + L"_indexes_"); os << name << "::" << value << " " << name << "::" << endl << "_xsd_" << name << "_convert () const" << "{" << "::xsd::cxx::tree::enum_comparator< " << char_type << " > c (_xsd_" << name << "_literals_);" << "const " << value << "* i (::std::lower_bound (" << endl << i_name << "," << endl << i_name << " + " << enum_count << "," << endl << "*this," << endl << "c));" << endl << "if (i == " << i_name << " + " << enum_count << " || " << "_xsd_" << name << "_literals_[*i] != *this)" << "{" << "throw ::xsd::cxx::tree::unexpected_enumerator < " << char_type << " > (*this);" << "}" << "return *i;" << "}"; } // literals and indexes // if (string_based) { if (enum_based) { os << "const " << char_type << "* const* " << name << "::" << endl << "_xsd_" << name << "_literals_ = " << fq_name (*be) << "::_xsd_" << ename (*be) << "_literals_;" << endl; } else { os << "const " << char_type << "* const " << name << "::" << endl << "_xsd_" << name << "_literals_[" << enum_count << "] =" << "{"; names ( e, names_enumerator_literal_, 0, 0, 0, &Enumeration::comma); os << "};"; } LiteralInfoList l; { EnumeratorLiteralInfo enumerator (*this, l); Traversal::Names names_enumerator (enumerator); names (e, names_enumerator); } l.sort (); os << "const " << name << "::" << value << " " << name << "::" << endl << "_xsd_" << name << "_indexes_[" << enum_count << "] =" << "{"; String fq_name (ns_scope + L"::" + name); for (LiteralInfoList::iterator b (l.begin ()), i (b), end (l.end ()); i != end; ++i) { if (i != b) os << "," << endl; os << fq_name << "::" << i->name_; } os << "};"; } // Register with type factory map. // if (polymorphic && polymorphic_p (e)) { // Note that we are using the original type name. // String const& name (ename (e)); // If this type is anonymous but substitutes, then it will // be registered as part of the substitution registration. // if (!anonymous_p (e) && !options.suppress_parsing ()) { os << "static" << endl << "const ::xsd::cxx::tree::type_factory_initializer< " << poly_plate << ", " << char_type << ", " << name << " >" << endl << "_xsd_" << name << "_type_factory_init (" << endl << strlit (e.name ()) << "," << endl << strlit (xml_ns_name (e)) << ");" << endl; } if ((!anonymous_p (e) || anonymous_substitutes_p (e)) && options.generate_comparison ()) { os << "static" << endl << "const ::xsd::cxx::tree::comparison_initializer< " << poly_plate << ", " << char_type << ", " << name << " >" << endl << "_xsd_" << name << "_comparison_init;" << endl; } } } virtual void comma (Type&) { os << "," << endl; } private: Traversal::Names names_enumerator_literal_; EnumeratorLiteral enumerator_literal_; }; // // struct Member: Traversal::Member, Context { Member (Context& c, String const& scope) : Context (c), scope_ (scope), init_value_ (c) { } virtual void traverse (Type& m) { if (skip (m)) return; // default_value // if (m.default_p ()) { SemanticGraph::Type& t (m.type ()); bool simple (true); if (m.is_a ()) { IsSimpleType test (simple); test.dispatch (t); } if (simple) { bool lit (false); { IsLiteralValue test (lit); test.dispatch (t); } if (!lit) { InitKind::Kind kind (InitKind::simple); { InitKind test (kind); test.dispatch (t); } String const& member (edefault_value_member (m)); String init_name; switch (kind) { case InitKind::data: { init_name = escape (L"_xsd_" + scope_ + member + L"data"); init_value_.data (init_name); init_value_.dispatch (t, m.value ()); break; } case InitKind::function: { init_name = escape (L"_xsd_" + scope_ + member + L"init"); os << "static " << scope_ << "::" << etype (m) << endl << init_name << " ()" << "{" << scope_ << "::" << etype (m) << " r;" << endl; init_value_.dispatch (t, m.value ()); os << "return r;" << "};"; break; } case InitKind::simple: break; } os << "const " << scope_ << "::" << etype (m) << " " << scope_ << "::" << member << " (" << endl; switch (kind) { case InitKind::data: { // Second dispatch. // init_value_.dispatch (t, m.value ()); break; } case InitKind::function: { os << init_name << " ()"; break; } case InitKind::simple: { init_value_.dispatch (t, m.value ()); break; } } os << ");" << endl; } } } } private: String scope_; InitValue init_value_; }; struct Element: Traversal::Element, Context { Element (Context& c) : Context (c) { } virtual void traverse (Type& e) { if (skip (e)) return; SemanticGraph::Complex& c ( dynamic_cast (e.scope ())); String const& member (emember (e)); String tr (etraits (e)); // traits type name String type (etype (e)); SemanticGraph::Type& t (e.type ()); bool fund (false); { IsFundamentalType traverser (fund); traverser.dispatch (t); } // Check if we need to handle xsi:type and substitution groups. // If this element's type is anonymous then we don't need to do // anything. Note that if the type is anonymous then it can't be // derived from which makes it impossible to substitute or // dynamically-type with xsi:type. // bool poly (polymorphic && polymorphic_p (t) && !anonymous_p (t)); os << "// " << comment (e.name ()) << endl << "//" << endl; if (poly) { os << "{" << auto_ptr << "< ::xsd::cxx::tree::type > tmp (" << endl << "::xsd::cxx::tree::type_factory_map_instance< " << poly_plate << ", " << char_type << " > ().create (" << endl << strlit (e.name ()) << "," << endl << (e.qualified_p () ? strlit (e.namespace_ ().name ()) : L + String ("\"\"")) << "," << endl; SemanticGraph::Complex* tc; if ((tc = dynamic_cast (&t)) != 0 && tc->abstract_p ()) os << "0,"; else os << "&::xsd::cxx::tree::factory_impl< " << type << " >,"; os << endl << (e.global_p () ? "true" : "false") << ", " << (e.qualified_p () ? "true" : "false") << ", " << "i, n, f, this));" << endl << "if (tmp.get () != 0)" << "{"; } else { if (e.qualified_p () && e.namespace_ ().name ()) { os << "if (n.name () == " << strlit (e.name ()) << " && " << "n.namespace_ () == " << strlit (e.namespace_ ().name ()) << ")" << "{"; } else { os << "if (n.name () == " << strlit (e.name ()) << " && " << "n.namespace_ ().empty ())" << "{"; } if (!fund) { os << auto_ptr << "< " << type << " > r (" << endl << tr << "::create (i, f"; if (t.is_a () && options.generate_any_type ()) os << " | " << flags_type << "::extract_content"; os << ", this));" << endl; } } // Checks. Disabled at the moment since they make it impossible to // parse valid instances where the same element is used in both // base and derived types. See the cxx/tree/name-clash/inheritance // test for details. // // if (max (e) != 1) { // sequence // } else if (min (e) == 0) { // optional // os << "if (!this->" << member << ")" << "{"; } else { // one // os << "if (!" << member << ".present ())" << "{"; } if (poly || !fund) { if (poly) { // Cast to static type. // os << auto_ptr << "< " << type << " > r (" << endl << "dynamic_cast< " << type << "* > (tmp.get ()));" << endl << "if (r.get ())" << endl << "tmp.release ();" << "else" << endl << "throw ::xsd::cxx::tree::not_derived< " << char_type << " > ();" << endl; } char const* r (std >= cxx_version::cxx11 ? "::std::move (r)" : "r"); if (max (e) != 1) { // sequence // os << "this->" << member << ".push_back (" << r << ");"; } else if (min (e) == 0) { // optional // os << "this->" << member << ".set (" << r << ");"; } else { // one // os << "this->" << member << ".set (" << r << ");"; } } else { if (max (e) != 1) { // sequence // os << "this->" << member << ".push_back (" << tr << "::create (i, f, this));"; } else if (min (e) == 0) { // optional // os << "this->" << member << ".set (" << tr << "::create (i, f, this));"; } else { // one // os << "this->" << member << ".set (" << tr << "::create (i, f, this));"; } } // Capture order. // if (ordered_p (c)) { SemanticGraph::Context& ctx (c.context ()); String const& t (ctx.get ("order-type")); String const& m (ctx.get ("order-member")); os << "this->" << m << ".push_back (" << endl << t << " (" << e.context ().get ("ordered-id-name"); // sequence // if (max (e) != 1) os << ", " << "this->" << member << ".size () - 1"; os << "));"; } os << "continue;"; // End of check block. // if (max (e) != 1) { // sequence // } else if (min (e) == 0) { // optional // os << "}"; } else { // one // os << "}"; } os << "}"; // if block if (poly) os << "}"; } }; struct ElementTest: Traversal::Element, Context { ElementTest (Context& c) : Context (c) { } virtual void traverse (Type& e) { if (skip (e)) return; if (max (e) == 1 && min (e) == 1) { // one // os << "if (!" << emember (e) << ".present ())" << "{" << "throw ::xsd::cxx::tree::expected_element< " << char_type << " > (" << endl << strlit (e.name ()) << "," << endl << (e.qualified_p () ? strlit (e.namespace_ ().name ()) : L + String ("\"\"")) << ");" << "}"; } } }; struct Any: Traversal::Any, Context { Any (Context& c) : Context (c) { } virtual void traverse (Type& a) { String const& member (emember (a)); SemanticGraph::Complex& c ( dynamic_cast (a.scope ())); String const& ns (a.definition_namespace ().name ()); String const& dom_doc (edom_document (c)); os << "// " << ename (a) << endl << "//" << endl << "if ("; for (SemanticGraph::Any::NamespaceIterator i (a.namespace_begin ()), e (a.namespace_end ()); i != e;) { if (*i == L"##any") { os << "true"; } else if (*i == L"##other") { if (ns) { // Note that here I assume that ##other does not include // unqualified names in a schema with target namespace. // This is not what the spec says but that seems to be // the consensus. // os << "(!n.namespace_ ().empty () && " << "n.namespace_ () != " << strlit (ns) << ")"; } else os << "!n.namespace_ ().empty ()"; } else if (*i == L"##local") { os << "n.namespace_ ().empty ()"; } else if (*i == L"##targetNamespace") { os << "n.namespace_ () == " << strlit (ns); } else { os << "n.namespace_ () == " << strlit (*i); } if (++i != e) os << " ||" << endl; } os << ")" << "{"; // Checks. // // if (max (a) != 1) { // sequence // } else if (min (a) == 0) { // optional // os << "if (!this->" << member << ")" << "{"; } else { // one // os << "if (!" << member << ".present ())" << "{"; } os << xerces_ns << "::DOMElement* r (" << endl << "static_cast< " << xerces_ns << "::DOMElement* > (" << endl << "this->" << dom_doc << " ().importNode (" << endl << "const_cast< " << xerces_ns << "::DOMElement* > (&i), true)));"; if (max (a) != 1) { // sequence // os << "this->" << member << ".push_back (r);"; } else if (min (a) == 0) { // optional // os << "this->" << member << ".set (r);"; } else { // one // os << "this->" << member << ".set (r);"; } // Capture order. // if (ordered_p (c)) { SemanticGraph::Context& ctx (c.context ()); String const& t (ctx.get ("order-type")); String const& m (ctx.get ("order-member")); os << "this->" << m << ".push_back (" << endl << t << " (" << a.context ().get ("ordered-id-name") << ", "; if (max (a) != 1) // sequence // os << "this->" << member << ".size () - 1"; else // optional & one // os << "0"; os << "));"; } os << "continue;"; // End of check block. // if (max (a) != 1) { // sequence // } else if (min (a) == 0) { // optional // os << "}"; } else { // one // os << "}"; } os << "}"; // if block } }; struct AnyTest: Traversal::Any, Context { AnyTest (Context& c) : Context (c) { } virtual void traverse (Type& a) { if (max (a) == 1 && min (a) == 1) { // one // os << "if (!" << emember (a) << ".present ())" << "{" << "throw ::xsd::cxx::tree::expected_element< " << char_type << " > (" << endl << L << "\"*\"," << endl << strlit (*a.namespace_begin ()) << ");" << "}"; } } }; struct Attribute: Traversal::Attribute, Context { Attribute (Context& c) : Context (c) { } virtual void traverse (Type& a) { String const& member (emember (a)); String const& tr (etraits (a)); // traits type name if (a.qualified_p () && a.namespace_ ().name ()) { os << "if (n.name () == " << strlit (a.name ()) << " && " << "n.namespace_ () == " << strlit (a.namespace_ ().name ()) << ")" << "{"; } else { os << "if (n.name () == " << strlit (a.name ()) << " && " << "n.namespace_ ().empty ())" << "{"; } os << "this->" << member << ".set (" << tr << "::create (i, f, this));"; os << "continue;" << "}"; } }; struct AnyAttribute: Traversal::AnyAttribute, Context { AnyAttribute (Context& c) : Context (c) { } virtual void traverse (Type& a) { String const& member (emember (a)); String const& ns (a.definition_namespace ().name ()); String const& dom_doc ( edom_document ( dynamic_cast (a.scope ()))); os << "// " << ename (a) << endl << "//" << endl << "if ("; // Note that we need to filter out namespaces for xmlns and // xsi. // for (SemanticGraph::Any::NamespaceIterator i (a.namespace_begin ()), e (a.namespace_end ()); i != e;) { if (*i == L"##any") { os << "(n.namespace_ () != " << "::xsd::cxx::xml::bits::xmlns_namespace< " << char_type << " > () &&" << endl << "n.namespace_ () != " << "::xsd::cxx::xml::bits::xsi_namespace< " << char_type << " > ())"; } else if (*i == L"##other") { if (ns) { // Note that here I assume that ##other does not include // unqualified names in a schema with target namespace. // This is not what the spec says but that seems to be // the consensus. // os << "(!n.namespace_ ().empty () &&" << endl << "n.namespace_ () != " << strlit (ns) << " &&" < () &&" << endl << "n.namespace_ () != " << "::xsd::cxx::xml::bits::xsi_namespace< " << char_type << " > ())"; } else os << "(!n.namespace_ ().empty () &&" << endl << "n.namespace_ () != " << "::xsd::cxx::xml::bits::xmlns_namespace< " << char_type << " > () &&" << endl << "n.namespace_ () != " << "::xsd::cxx::xml::bits::xsi_namespace< " << char_type << " > ())"; } else if (*i == L"##local") { os << "n.namespace_ ().empty ()"; } else if (*i == L"##targetNamespace") { os << "n.namespace_ () == " << strlit (ns); } else { os << "n.namespace_ () == " << strlit (*i); } if (++i != e) os << " ||" << endl; } os << ")" << "{" << xerces_ns << "::DOMAttr* r (" << endl << "static_cast< " << xerces_ns << "::DOMAttr* > (" << endl << "this->" << dom_doc << " ().importNode (" << endl << "const_cast< " << xerces_ns << "::DOMAttr* > (&i), true)));" << "this->" << member << " .insert (r);" << "continue;" << "}"; } }; struct AttributeTest: Traversal::Attribute, Context { AttributeTest (Context& c) : Context (c) { } virtual void traverse (Type& a) { String const& member (emember (a)); if (!a.optional_p () || a.default_p ()) { os << "if (!" << member << ".present ())" << "{"; if (a.default_p ()) { os << "this->" << member << ".set (" << edefault_value (a) << " ());"; } else os << "throw ::xsd::cxx::tree::expected_attribute< " << char_type << " > (" << endl << strlit (a.name ()) << "," << endl << (a.qualified_p () ? strlit (a.namespace_ ().name ()) : L + String ("\"\"")) << ");"; os << "}"; } } }; // // struct CtorBase: Traversal::Complex, Traversal::Enumeration, Traversal::Type, Context { // If base_arg is empty then no base argument is generated. // CtorBase (Context& c, CtorArgType at, String const& base_arg) : Context (c), args_ (c, at, base_arg) { } virtual void traverse (SemanticGraph::Type&) { if (args_.base_arg_) os << args_.base_arg_; } virtual void traverse (SemanticGraph::Enumeration&) { if (args_.base_arg_) os << args_.base_arg_; } void traverse (SemanticGraph::Complex& c) { args_.traverse (c); } private: // No need to traverse AnyAttribute since it is always mapped // to a sequence. // struct Args: Traversal::Complex, Traversal::Enumeration, Traversal::Type, Traversal::Any, Traversal::Element, Traversal::Attribute, Context { Args (Context& c, CtorArgType at, String const& base_arg) : Context (c), arg_type_ (at), base_arg_ (base_arg), first_ (true) { *this >> inherits_ >> *this; *this >> names_ >> *this; } virtual void traverse (SemanticGraph::Type&) { if (base_arg_) os << comma () << base_arg_; } virtual void traverse (SemanticGraph::Enumeration&) { if (base_arg_) os << comma () << base_arg_; } virtual void traverse (SemanticGraph::Any& a) { if (!options.generate_wildcard ()) return; if (min (a) == 1 && max (a) == 1) { // one // os << comma () << ename (a); } } virtual void traverse (SemanticGraph::Element& e) { if (!skip (e) && min (e) == 1 && max (e) == 1) { // one // bool move (false); if (std >= cxx_version::cxx11) { switch (arg_type_) { case CtorArgType::complex_auto_ptr: { bool simple (true); IsSimpleType t (simple); t.dispatch (e.type ()); move = !simple; break; } case CtorArgType::poly_auto_ptr: { move = polymorphic && polymorphic_p (e.type ()); break; } case CtorArgType::type: break; } } os << comma () << (move ? "std::move (" : "") << ename (e) << (move ? ")" : ""); } } virtual void traverse (SemanticGraph::Attribute& a) { // Note that we are not including attributes with default // or required fixed values here. // if (min (a) == 1 && !a.fixed_p ()) { // one // os << comma () << ename (a); } } using Complex::traverse; private: String comma () { bool tmp (first_); first_ = false; return tmp ? "" : ",\n"; } public: CtorArgType arg_type_; String base_arg_; private: bool first_; Traversal::Inherits inherits_; Traversal::Names names_; }; Args args_; }; struct CtorMember: Traversal::Element, Traversal::Attribute, Context { CtorMember (Context& c, CtorArgType at) : Context (c), arg_type_ (at) { } virtual void traverse (SemanticGraph::Element& e) { if (skip (e)) return; String const& member (emember (e)); if (max (e) != 1) { // sequence // os << "," << endl << " " << member << " (this)"; } else if (min (e) == 0) { // optional // os << "," << endl << " " << member << " (this)"; } else { // one // bool move (false); if (std >= cxx_version::cxx11) { switch (arg_type_) { case CtorArgType::complex_auto_ptr: { bool simple (true); IsSimpleType t (simple); t.dispatch (e.type ()); move = !simple; break; } case CtorArgType::poly_auto_ptr: { move = polymorphic && polymorphic_p (e.type ()); break; } case CtorArgType::type: break; } } os << "," << endl << " " << member << " (" << (move ? "std::move (" : "") << ename (e) << (move ? ")" : "") << ", this)"; } } virtual void traverse (SemanticGraph::Attribute& a) { String const& member (emember (a)); bool def (a.default_p ()); if (min (a) == 0 && !def) { // optional // os << "," << endl << " " << member << " (this)"; } else { // one // if (def) { // This is an attribute with default or fixed value. We are // going to initialize it to its default value. // os << "," << endl << " " << member << " (" << edefault_value (a) << " (), this)"; } else { os << "," << endl << " " << member << " (" << ename (a) << ", this)"; } } } private: CtorArgType arg_type_; }; struct CtorAny: Traversal::Any, Traversal::AnyAttribute, Context { CtorAny (Context& c) : Context (c) { } virtual void traverse (SemanticGraph::Any& a) { String const& member (emember (a)); String const& dom_doc ( edom_document ( dynamic_cast (a.scope ()))); if (max (a) != 1) { // sequence // os << "," << endl << " " << member << " (this->" << dom_doc << " ())"; } else if (min (a) == 0) { // optional // os << "," << endl << " " << member << " (this->" << dom_doc << " ())"; } else { // one // os << "," << endl << " " << member << " (" << ename (a) << ", this->" << dom_doc << " ())"; } } virtual void traverse (SemanticGraph::AnyAttribute& a) { String const& dom_doc ( edom_document ( dynamic_cast (a.scope ()))); os << "," << endl << " " << emember (a) << " (this->" << dom_doc << " ())"; } }; struct CopyMember: Traversal::Member, Context { CopyMember (Context& c, String const& arg_name_) : Context (c), arg_name (arg_name_) { } virtual void traverse (SemanticGraph::Member& m) { if (skip (m)) return; String const& member (emember (m)); os << "," << endl << " " << member << " (" << arg_name << "." << member << ", f, this)"; } private: String arg_name; }; struct CopyAny: Traversal::Any, Traversal::AnyAttribute, Context { CopyAny (Context& c, String const& arg_name_) : Context (c), arg_name (arg_name_) { } virtual void traverse (SemanticGraph::Any& a) { String const& member (emember (a)); String const& dom_doc ( edom_document ( dynamic_cast (a.scope ()))); os << "," << endl << " " << member << " (" << arg_name << "." << member << ", this->" << dom_doc << " ())"; } virtual void traverse (SemanticGraph::AnyAttribute& a) { String const& member (emember (a)); String const& dom_doc ( edom_document ( dynamic_cast (a.scope ()))); os << "," << endl << " " << member << " (" << arg_name << "." << member << ", this->" << dom_doc << " ())"; } private: String arg_name; }; struct AssignMember: Traversal::Member, Context { AssignMember (Context& c) : Context (c) { } virtual void traverse (SemanticGraph::Member& m) { if (skip (m)) return; String const& member (emember (m)); os << "this->" << member << " = x." << member << ";"; } }; struct AssignAny: Traversal::Any, Traversal::AnyAttribute, Context { AssignAny (Context& c) : Context (c) { } virtual void traverse (SemanticGraph::Any& a) { String const& member (emember (a)); os << "this->" << member << " = x." << member << ";"; } virtual void traverse (SemanticGraph::AnyAttribute& a) { String const& member (emember (a)); os << "this->" << member << " = x." << member << ";"; } }; // Element parsing c-tor initializers. // struct ElementCtorMember: Traversal::Member, Context { ElementCtorMember (Context& c) : Context (c) { } virtual void traverse (Type& m) { if (skip (m)) return; String const& member (emember (m)); os << "," << endl << " " << member << " (this)"; } }; struct ElementCtorAny: Traversal::Any, Traversal::AnyAttribute, Context { ElementCtorAny (Context& c) : Context (c) { } virtual void traverse (SemanticGraph::Any& a) { String const& member (emember (a)); String const& dom_doc ( edom_document ( dynamic_cast (a.scope ()))); os << "," << endl << " " << member << " (this->" << dom_doc << " ())"; } virtual void traverse (SemanticGraph::AnyAttribute& a) { String const& member (emember (a)); String const& dom_doc ( edom_document ( dynamic_cast (a.scope ()))); os << "," << endl << " " << member << " (this->" << dom_doc << " ())"; } }; // Default c-tor member initializer. // struct DefaultCtorMemberInit: Traversal::Element, Traversal::Attribute, Context { DefaultCtorMemberInit (Context& c) : Context (c) { } virtual void traverse (SemanticGraph::Element& e) { if (skip (e)) return; String const& member (emember (e)); os << "," << endl << " " << member << " (this)"; } virtual void traverse (SemanticGraph::Attribute& a) { String const& member (emember (a)); if (a.default_p ()) { // This is an attribute with default or fixed value. We are // going to initialize it to its default value. // os << "," << endl << " " << member << " (" << edefault_value (a) << " (), this)"; } else os << "," << endl << " " << member << " (this)"; } }; struct DefaultCtorAnyInit: Traversal::Any, Traversal::AnyAttribute, Context { DefaultCtorAnyInit (Context& c) : Context (c) { } virtual void traverse (SemanticGraph::Any& a) { String const& member (emember (a)); String const& dom_doc ( edom_document ( dynamic_cast (a.scope ()))); os << "," << endl << " " << member << " (this->" << dom_doc << " ())"; } virtual void traverse (SemanticGraph::AnyAttribute& a) { String const& member (emember (a)); String const& dom_doc ( edom_document ( dynamic_cast (a.scope ()))); os << "," << endl << " " << member << " (this->" << dom_doc << " ())"; } }; // Test whether the base has comparison operators. // struct HasComparisonOperator: Traversal::Fundamental::Type, Traversal::List, Traversal::Union, Traversal::Complex, Traversal::Enumeration, Traversal::Member, Traversal::Any, Traversal::AnyAttribute, Context { // generate should initially be false. // HasComparisonOperator (Context& c, bool& generate) : Context (c), generate_ (generate) { *this >> inherits_ >> *this; *this >> names_ >> *this; } virtual void traverse (SemanticGraph::Fundamental::Type&) { // All built-in types are comparable. generate_ = true; } virtual void traverse (SemanticGraph::List&) { generate_ = true; } virtual void traverse (SemanticGraph::Union&) { generate_ = true; } virtual void traverse (SemanticGraph::Enumeration& e) { Traversal::Enumeration::inherits (e); } virtual void traverse (SemanticGraph::Complex& c) { Complex::names (c); if (!generate_) Complex::inherits (c); } virtual void traverse (SemanticGraph::Member& m) { if (!skip (m)) generate_ = true; } virtual void traverse (SemanticGraph::Any&) { if (options.generate_wildcard ()) generate_ = true; } virtual void traverse (SemanticGraph::AnyAttribute&) { if (options.generate_wildcard ()) generate_ = true; } private: bool& generate_; Traversal::Inherits inherits_; Traversal::Names names_; }; // // struct MemberComparison: Traversal::Element, Traversal::Attribute, Context { MemberComparison (Context& c) : Context (c) { } virtual void traverse (SemanticGraph::Element& e) { if (skip (e)) return; String const& aname (eaname (e)); // Check if we need to handle xsi:type and substitution groups. // If this element's type is anonymous then we don't need to do // anything. Note that if the type is anonymous then it can't be // derived from which makes it impossible to substitute or // dynamically-type with xsi:type. // SemanticGraph::Type& t (e.type ()); bool poly (polymorphic && polymorphic_p (t) && !anonymous_p (t)); if (!poly) { os << "if (!(x." << aname << " () == y." << aname << " ()))" << endl << "return false;" << endl; } else { os << "{" << "::xsd::cxx::tree::comparison_map< " << char_type << " >& cm (" << endl << "::xsd::cxx::tree::comparison_map_instance< " << poly_plate << ", " << char_type << " > ());" << endl; if (max (e) != 1) { // sequence // String const& scope (ename (e.scope ())); os << scope << "::" << econtainer (e) << " a (x." << aname << " ()), b (y." << aname << " ());" << endl; os << "if (a.size () != b.size ())" << endl << "return false;" << endl; os << "for (" << scope << "::" << econst_iterator (e) << endl << "ai (a.begin ()), bi (b.begin ()), " << "ae (a.end ()), be (b.end ());" << endl << "ai != ae; ++ai, ++bi)" << "{" << "if (!cm.compare (*ai, *bi))" << endl << "return false;" << "}"; } else if (min (e) == 0) { // optional // String const& scope (ename (e.scope ())); os << scope << "::" << econtainer (e) << " a (x." << aname << " ()), b (y." << aname << " ());" << endl; os << "if (!a || !b)" << "{" << "if (a.present () != b.present ())" << endl << "return false;" << "}" << "else" << "{" << "if (!cm.compare (*a, *b))" << endl << "return false;" << "}"; } else { // one // os << "if (!cm.compare (x." << aname << " (), y." << aname << " ()))" << endl << "return false;"; } os << "}"; } } virtual void traverse (SemanticGraph::Attribute& a) { String const& aname (eaname (a)); os << "if (!(x." << aname << " () == y." << aname << " ()))" << endl << "return false;" << endl; } }; struct AnyComparison: Traversal::Any, Traversal::AnyAttribute, Context { AnyComparison (Context& c) : Context (c) { } virtual void traverse (SemanticGraph::Any& a) { String const& aname (eaname (a)); if (max (a) == 1 && min (a) == 1) os << "if (!x." << aname << " ().isEqualNode (&y." << aname << " ()))"; else os << "if (!(x." << aname << " () == y." << aname << " ()))"; os << endl << "return false;" << endl; } virtual void traverse (SemanticGraph::AnyAttribute& a) { String const& aname (eaname (a)); os << "if (!(x." << aname << " () == y." << aname << " ()))" << endl << "return false;" << endl; } }; // Check whether a type has a parse() function (i.e., has any // members, recursively). // struct HasParseFunction: Traversal::Complex, Traversal::Element, Traversal::Any, Traversal::Attribute, Traversal::AnyAttribute, Context { HasParseFunction (Context& c, bool& has_el, bool& has_at) : Context (c), has_el_ (has_el), has_at_ (has_at) { *this >> names_ >> *this; *this >> inherits_ >> *this; } virtual void traverse (SemanticGraph::Complex& c) { if (mixed_p (c) && !c.context ().count ("mixed-in-base")) has_el_ = true; names (c); if (!(has_el_ && has_at_)) inherits (c); } virtual void traverse (SemanticGraph::Element&) { has_el_ = true; } virtual void traverse (SemanticGraph::Any&) { has_el_ = true; } virtual void traverse (SemanticGraph::Attribute&) { has_at_ = true; } virtual void traverse (SemanticGraph::AnyAttribute&) { if (options.generate_wildcard ()) has_at_ = true; } private: bool& has_el_; bool& has_at_; Traversal::Names names_; Traversal::Inherits inherits_; }; // // struct FacetArray: Traversal::Complex, Context { FacetArray (Context& c) : Context (c) { } virtual void traverse (Type& c) { Facets f; FacetCollector col (f); col.traverse (c); for (Facets::const_iterator i (f.begin ()); i != f.end (); ++i) { if (i->first == L"fractionDigits") os << "{::xsd::cxx::tree::facet::fraction_digits, " << i->second << "UL}," << endl; else if (i->first == L"totalDigits") os << "{::xsd::cxx::tree::facet::total_digits, " << i->second << "UL}," << endl; } } private: typedef map Facets; struct FacetCollector: Traversal::Complex { FacetCollector (Facets& facets) : facets_ (facets) { *this >> inherits_ >> *this; } virtual void traverse (Type& c) { if (c.inherits_p ()) { // First collect our base so that we can override its // facets. // inherits (c); using SemanticGraph::Restricts; if (Restricts* r = dynamic_cast (&c.inherits ())) { if (!r->facet_empty ()) { Restricts::FacetIterator i (r->facet_find ("totalDigits")); if (i != r->facet_end ()) facets_[i->first] = i->second; i = r->facet_find ("fractionDigits"); if (i != r->facet_end ()) facets_[i->first] = i->second; } } } } private: Traversal::Inherits inherits_; Facets& facets_; }; }; // // struct Complex: Traversal::Complex, Context { Complex (Context& c) : Context (c), member_name_ (c), any_ (c), element_ (c), any_test_ (c), element_test_ (c), attribute_ (c), attribute_test_ (c), any_attribute_ (c), default_ctor_any_init_ (c), default_ctor_member_init_ (c), ctor_any_ (c), ctor_member_ (c, CtorArgType::type), element_ctor_any_ (c), element_ctor_member_ (c), assign_any_ (c), assign_member_ (c), comparison_any_ (c), comparison_member_ (c), facet_array_ (c) { bool gen_wildcard (options.generate_wildcard ()); inherits_member_ >> member_name_; names_element_ >> element_; if (gen_wildcard) names_element_ >> any_; names_element_test_ >> element_test_; if (gen_wildcard) names_element_test_ >> any_test_; names_attribute_ >> attribute_; names_attribute_test_ >> attribute_test_; names_any_attribute_ >> any_attribute_; default_ctor_init_names_ >> default_ctor_member_init_; if (gen_wildcard) default_ctor_init_names_ >> default_ctor_any_init_; ctor_names_ >> ctor_member_; if (gen_wildcard) ctor_names_ >> ctor_any_; element_ctor_names_ >> element_ctor_member_; if (gen_wildcard) element_ctor_names_ >> element_ctor_any_; assign_names_ >> assign_member_; if (gen_wildcard) assign_names_ >> assign_any_; comparison_names_ >> comparison_member_; if (gen_wildcard) comparison_names_ >> comparison_any_; } virtual void traverse (Type& c) { bool gen_wildcard (options.generate_wildcard ()); String name (ename (c)); // If renamed name is empty then we do not need to generate // anything for this type. // bool renamed (renamed_type (c, name)); if (renamed && !name) return; SemanticGraph::Context& ctx (c.context ()); bool mixed (mixed_p (c) && !ctx.count ("mixed-in-base")); bool ordered (ordered_p (c) && !ctx.count ("order-in-base")); bool string_based (false); { IsStringBasedType t (string_based); t.dispatch (c); } SemanticGraph::Enumeration* enum_base (0); { IsEnumBasedType t (enum_base); t.dispatch (c); } bool facets (false); String base; // base type name if (c.inherits_p ()) { // Get base name. // std::wostringstream o; BaseTypeName base_type (*this, o); Traversal::Inherits inherits_type (base_type); // Cannot use inherits_none here because need the // result in a string. // inherits (c, inherits_type); base = o.str (); // See if we have any facets that we need to handle. // using SemanticGraph::Restricts; using SemanticGraph::Fundamental::Decimal; if (Restricts* r = dynamic_cast (&c.inherits ())) { if (!r->facet_empty () && (r->facet_find ("fractionDigits") != r->facet_end () || r->facet_find ("totalDigits") != r->facet_end ()) && ultimate_base (c).is_a ()) facets = true; } } else base = any_type; os << "// " << name << endl << "//" << endl << endl; // // { Member member (*this, name); Traversal::Names names_member (member); names (c, names_member); } // facets // if (facets) { os << "static const ::xsd::cxx::tree::facet _xsd_" << name << "_facet_table[] = " << "{"; facet_array_.traverse (c); os << "{::xsd::cxx::tree::facet::none, 0UL}" << "};"; } // c-tors // bool generate_no_base_ctor (false); { GenerateWithoutBaseCtor t (generate_no_base_ctor); t.traverse (c); } bool has_complex_non_op_args (false); bool has_poly_non_op_args (false); bool complex_poly_args_clash (true); { HasComplexPolyNonOptArgs t (*this, true, has_complex_non_op_args, has_poly_non_op_args, complex_poly_args_clash); t.traverse (c); } // default c-tor // if (options.generate_default_ctor ()) { bool generate (false); { GenerateDefaultCtor t (*this, generate, generate_no_base_ctor); t.traverse (c); } if (generate) { os << name << "::" << endl << name << " ()" << endl << ": " << base << " ()"; if (edom_document_member_p (c)) { os << "," << endl << " " << edom_document_member (c) << " (" << "::xsd::cxx::xml::dom::create_document< " << char_type << " > ())"; } if (mixed) { os << "," << endl << " " << ctx.get ("mixed-member") << " (this)"; } names (c, default_ctor_init_names_); os << "{"; if (facets) os << "this->_facet_table (_xsd_" << name << "_facet_table);"; os << "}"; } } // c-tor (base, all-non-optional-members) // if (options.generate_from_base_ctor ()) { bool generate (false); { GenerateFromBaseCtor t (*this, generate); t.traverse (c); } if (generate) { bool has_complex_non_op_args (false); bool has_poly_non_op_args (false); bool complex_poly_args_clash (true); { HasComplexPolyNonOptArgs t (*this, false, has_complex_non_op_args, has_poly_non_op_args, complex_poly_args_clash); t.traverse (c); } String base_arg ( L"_xsd_" + ename (c.inherits ().base ()) + L"_base"); os << name << "::" << endl << name << " (const "; inherits (c, inherits_member_); os << "& " << base_arg; { FromBaseCtorArg args (*this, CtorArgType::type, true); Traversal::Names args_names (args); names (c, args_names); } os << ")" << endl << ": " << base << " (" << base_arg << ")"; if (edom_document_member_p (c)) { os << "," << endl << " " << edom_document_member (c) << " (" << "::xsd::cxx::xml::dom::create_document< " << char_type << " > ())"; } if (mixed) { os << "," << endl << " " << ctx.get ("mixed-member") << " (this)"; } names (c, ctor_names_); os << "{"; if (facets) os << "this->_facet_table (_xsd_" << name << "_facet_table);"; os << "}"; // If we have any complex arguments in the previous c-tor // then also generate the auto_ptr version. // if (has_complex_non_op_args) { CtorArgType const at (CtorArgType::complex_auto_ptr); os << name << "::" << endl << name << " (const "; inherits (c, inherits_member_); os << "& " << base_arg; { FromBaseCtorArg args (*this, at, true); Traversal::Names args_names (args); names (c, args_names); } os << ")" << endl << ": " << base << " (" << base_arg << ")"; if (edom_document_member_p (c)) { os << "," << endl << " " << edom_document_member (c) << " (" << "::xsd::cxx::xml::dom::create_document< " << char_type << " > ())"; } if (mixed) { os << "," << endl << " " << ctx.get ("mixed-member") << " (this)"; } { CtorMember t (*this, at); Traversal::Names n (t); if (gen_wildcard) n >> ctor_any_; names (c, n); } os << "{"; if (facets) os << "this->_facet_table (_xsd_" << name << "_facet_table);"; os << "}"; } // If we are generating polymorphic code then we also need to // provide auto_ptr version for every polymorphic type. // if (polymorphic && has_poly_non_op_args && !complex_poly_args_clash) { CtorArgType const at (CtorArgType::poly_auto_ptr); os << name << "::" << endl << name << " (const "; inherits (c, inherits_member_); os << "& " << base_arg; { FromBaseCtorArg args (*this, at, true); Traversal::Names args_names (args); names (c, args_names); } os << ")" << endl << ": " << base << " (" << base_arg << ")"; if (edom_document_member_p (c)) { os << "," << endl << " " << edom_document_member (c) << " (" << "::xsd::cxx::xml::dom::create_document< " << char_type << " > ())"; } if (mixed) { os << "," << endl << " " << ctx.get ("mixed-member") << " (this)"; } { CtorMember t (*this, at); Traversal::Names n (t); if (gen_wildcard) n >> ctor_any_; names (c, n); } os << "{"; if (facets) os << "this->_facet_table (_xsd_" << name << "_facet_table);"; os << "}"; } } } // c-tor (all-non-optional-members) // if (generate_no_base_ctor) { CtorArgType const at (CtorArgType::type); os << name << "::" << endl << name << " ("; { CtorArgsWithoutBase ctor_args (*this, at, true, true); ctor_args.dispatch (c); } os << ")" << endl << ": " << base << " ("; { CtorBase base (*this, at, ""); Traversal::Inherits inherits_base (base); inherits (c, inherits_base); } os << ")"; if (edom_document_member_p (c)) { os << "," << endl << " " << edom_document_member (c) << " (" << "::xsd::cxx::xml::dom::create_document< " << char_type << " > ())"; } if (mixed) { os << "," << endl << " " << ctx.get ("mixed-member") << " (this)"; } names (c, ctor_names_); os << "{"; if (facets) os << "this->_facet_table (_xsd_" << name << "_facet_table);"; os << "}"; // If we have any complex arguments in the previous c-tor // then also generate the auto_ptr version. One case where // this c-tor will be generated is restriction of anyType. // if (has_complex_non_op_args) { CtorArgType const at (CtorArgType::complex_auto_ptr); os << name << "::" << endl << name << " ("; { CtorArgsWithoutBase ctor_args (*this, at, true, true); ctor_args.dispatch (c); } os << ")" << endl << ": " << base << " ("; { CtorBase base (*this, at, ""); Traversal::Inherits inherits_base (base); inherits (c, inherits_base); } os << ")"; if (edom_document_member_p (c)) { os << "," << endl << " " << edom_document_member (c) << " (" << "::xsd::cxx::xml::dom::create_document< " << char_type << " > ())"; } if (mixed) { os << "," << endl << " " << ctx.get ("mixed-member") << " (this)"; } { CtorMember t (*this, at); Traversal::Names n (t); if (gen_wildcard) n >> ctor_any_; names (c, n); } os << "{"; if (facets) os << "this->_facet_table (_xsd_" << name << "_facet_table);"; os << "}"; } // If we are generating polymorphic code then we also need to // provide auto_ptr version for every polymorphic type. // if (polymorphic && has_poly_non_op_args && !complex_poly_args_clash) { CtorArgType const at (CtorArgType::poly_auto_ptr); os << name << "::" << endl << name << " ("; { CtorArgsWithoutBase ctor_args (*this, at, true, true); ctor_args.dispatch (c); } os << ")" << endl << ": " << base << " ("; { CtorBase base (*this, at, ""); Traversal::Inherits inherits_base (base); inherits (c, inherits_base); } os << ")"; if (edom_document_member_p (c)) { os << "," << endl << " " << edom_document_member (c) << " (" << "::xsd::cxx::xml::dom::create_document< " << char_type << " > ())"; } if (mixed) { os << "," << endl << " " << ctx.get ("mixed-member") << " (this)"; } { CtorMember t (*this, at); Traversal::Names n (t); if (gen_wildcard) n >> ctor_any_; names (c, n); } os << "{"; if (facets) os << "this->_facet_table (_xsd_" << name << "_facet_table);"; os << "}"; } } if (string_based) { // We might not have the value type if this enum is customized. // if (enum_base != 0 && enum_base->context ().count ("value")) { // c-tor (enum-value, all-non-optional-members) // CtorArgType const at (CtorArgType::type); String base_arg (L"_xsd_" + ename (*enum_base) + L"_base"); os << name << "::" << endl << name << " (" << fq_name (*enum_base) << "::" << evalue (*enum_base) << " " << base_arg; { CtorArgsWithoutBase ctor_args (*this, at, true, false); ctor_args.dispatch (c); } os << ")" << endl << ": " << base << " ("; { CtorBase base (*this, at, base_arg); Traversal::Inherits inherits_base (base); inherits (c, inherits_base); } os << ")"; if (edom_document_member_p (c)) { os << "," << endl << " " << edom_document_member (c) << " (" << "::xsd::cxx::xml::dom::create_document< " << char_type << " > ())"; } // Cannot be mixed. names (c, ctor_names_); os << "{"; if (facets) os << "this->_facet_table (_xsd_" << name << "_facet_table);"; os << "}"; } CtorArgType const at (CtorArgType::type); String base_arg (L"_xsd_" + ename (ultimate_base (c)) + L"_base"); // c-tor (const char*, all-non-optional-members) // os << name << "::" << endl << name << " (const " << char_type << "* " << base_arg; { CtorArgsWithoutBase ctor_args (*this, at, true, false); ctor_args.dispatch (c); } os << ")" << endl << ": " << base << " ("; { CtorBase base (*this, at, base_arg); Traversal::Inherits inherits_base (base); inherits (c, inherits_base); } os << ")"; if (edom_document_member_p (c)) { os << "," << endl << " " << edom_document_member (c) << " (" << "::xsd::cxx::xml::dom::create_document< " << char_type << " > ())"; } // Cannot be mixed. names (c, ctor_names_); os << "{"; if (facets) os << "this->_facet_table (_xsd_" << name << "_facet_table);"; os << "}"; // c-tor (const std::string&, all-non-optional-members) // os << name << "::" << endl << name << " (const " << string_type << "& " << base_arg; { CtorArgsWithoutBase ctor_args (*this, at, true, false); ctor_args.dispatch (c); } os << ")" << endl << ": " << base << " ("; { CtorBase base (*this, at, base_arg); Traversal::Inherits inherits_base (base); inherits (c, inherits_base); } os << ")"; if (edom_document_member_p (c)) { os << "," << endl << " " << edom_document_member (c) << " (" << "::xsd::cxx::xml::dom::create_document< " << char_type << " > ())"; } // Cannot be mixed. names (c, ctor_names_); os << "{"; if (facets) os << "this->_facet_table (_xsd_" << name << "_facet_table);"; os << "}"; } // c-tor (ultimate-base, all-non-optional-members) // { CtorArgType const at (CtorArgType::type); os << name << "::" << endl << name << " ("; String base_arg; { CtorArgs ctor_args (*this, at, base_arg); ctor_args.dispatch (c); } os << ")" << endl << ": " << base << " ("; { CtorBase base (*this, at, base_arg); Traversal::Inherits inherits_base (base); inherits (c, inherits_base); } os << ")"; if (edom_document_member_p (c)) { os << "," << endl << " " << edom_document_member (c) << " (" << "::xsd::cxx::xml::dom::create_document< " << char_type << " > ())"; } if (mixed) { os << "," << endl << " " << ctx.get ("mixed-member") << " (this)"; } names (c, ctor_names_); os << "{"; if (facets) os << "this->_facet_table (_xsd_" << name << "_facet_table);"; os << "}"; } // If we have any complex arguments in the previous c-tor // then also generate the auto_ptr version. // if (has_complex_non_op_args) { CtorArgType const at (CtorArgType::complex_auto_ptr); String base_arg; os << name << "::" << endl << name << " ("; { CtorArgs ctor_args (*this, at, base_arg); ctor_args.dispatch (c); } os << ")" << endl << ": " << base << " ("; { CtorBase base (*this, at, base_arg); Traversal::Inherits inherits_base (base); inherits (c, inherits_base); } os << ")"; if (edom_document_member_p (c)) { os << "," << endl << " " << edom_document_member (c) << " (" << "::xsd::cxx::xml::dom::create_document< " << char_type << " > ())"; } if (mixed) { os << "," << endl << " " << ctx.get ("mixed-member") << " (this)"; } { CtorMember t (*this, at); Traversal::Names n (t); if (gen_wildcard) n >> ctor_any_; names (c, n); } os << "{"; if (facets) os << "this->_facet_table (_xsd_" << name << "_facet_table);"; os << "}"; } // If we are generating polymorphic code then we also need to // provide auto_ptr version for every polymorphic type. // if (polymorphic && has_poly_non_op_args && !complex_poly_args_clash) { CtorArgType const at (CtorArgType::poly_auto_ptr); String base_arg; os << name << "::" << endl << name << " ("; { CtorArgs ctor_args (*this, at, base_arg); ctor_args.dispatch (c); } os << ")" << endl << ": " << base << " ("; { CtorBase base (*this, at, base_arg); Traversal::Inherits inherits_base (base); inherits (c, inherits_base); } os << ")"; if (edom_document_member_p (c)) { os << "," << endl << " " << edom_document_member (c) << " (" << "::xsd::cxx::xml::dom::create_document< " << char_type << " > ())"; } if (mixed) { os << "," << endl << " " << ctx.get ("mixed-member") << " (this)"; } { CtorMember t (*this, at); Traversal::Names n (t); if (gen_wildcard) n >> ctor_any_; names (c, n); } os << "{"; if (facets) os << "this->_facet_table (_xsd_" << name << "_facet_table);"; os << "}"; } // copy c-tor // os << name << "::" << endl << name << " (const " << name << "& x," << endl << flags_type << " f," << endl << container << "* c)" << endl << ": " << base << " (x, f, c)"; if (edom_document_member_p (c)) { os << "," << endl << " " << edom_document_member (c) << " (" << "::xsd::cxx::xml::dom::create_document< " << char_type << " > ())"; } if (mixed) { String const& m (ctx.get ("mixed-member")); os << "," << endl << " " << m << " (x." << m << ", f, this)"; } if (ordered) { String const& m (ctx.get ("order-member")); os << "," << endl << " " << m << " (x." << m << ")"; } { CopyAny copy_any (*this, "x"); CopyMember copy_member (*this, "x"); Traversal::Names names; names >> copy_member; if (gen_wildcard) names >> copy_any; Complex::names (c, names); } os << "{"; if (facets) os << "this->_facet_table (_xsd_" << name << "_facet_table);"; os << "}"; // // bool he (has (c)); bool hae (has (c)); bool ha (has (c)); bool haa (has (c)); // // if (!options.suppress_parsing ()) { // c-tor (xercesc::DOMElement) // os << name << "::" << endl << name << " (const " << xerces_ns << "::DOMElement& e," << endl << flags_type << " f," << endl << container << "* c)" << endl << ": " << base << " (e, f"; if (he || ha || hae || (haa && gen_wildcard) || mixed) os << " | " << flags_type << "::base"; os << ", c)"; if (edom_document_member_p (c)) { os << "," << endl << " " << edom_document_member (c) << " (" << "::xsd::cxx::xml::dom::create_document< " << char_type << " > ())"; } if (mixed) { os << "," << endl << " " << ctx.get ("mixed-member") << " (this)"; } names (c, element_ctor_names_); os << "{"; if (facets) os << "this->_facet_table (_xsd_" << name << "_facet_table);" << endl; bool base_has_el (false), base_has_at (false); // We are only interested in this information if we are // generating our own parse(). // if (he || ha || hae || (haa && gen_wildcard) || mixed) { if (c.inherits_p ()) { HasParseFunction test (*this, base_has_el, base_has_at); test.dispatch (c.inherits ().base ()); } } //@@ Throw if p is not exhausted at the end. // if (he || ha || hae || (haa && gen_wildcard) || mixed) os << "if ((f & " << flags_type << "::base) == 0)" << "{" << parser_type << " p (e, " << (he || hae || base_has_el || mixed_p (c) ? "true, " : "false, ") << (mixed_p (c) ? "true, " : "false, ") << (ha || (haa && gen_wildcard) || base_has_at ? "true" : "false") << ");" << "this->" << unclash (name, "parse") << " (p, f);" << "}"; os << "}"; bool simple (true); { IsSimpleType t (simple); t.dispatch (c); } if (simple) { // c-tor (xercesc::DOMAttr) // os << name << "::" << endl << name << " (const " << xerces_ns << "::DOMAttr& a," << endl << flags_type << " f," << endl << container << "* c)" << endl << ": " << base << " (a, f, c)" << "{"; if (facets) os << "this->_facet_table (_xsd_" << name << "_facet_table);"; os << "}"; // c-tor (string const&, xercesc::DOMElement) // os << name << "::" << endl << name << " (const " << string_type << "& s," << endl << "const " << xerces_ns << "::DOMElement* e," << endl << flags_type << " f," << endl << container << "* c)" << endl << ": " << base << " (s, e, f, c)" << "{"; if (facets) os << "this->_facet_table (_xsd_" << name << "_facet_table);"; os << "}"; } if (he || ha || hae || (haa && gen_wildcard) || mixed) { os << "void " << name << "::" << endl << unclash (name, "parse") << " (" << parser_type << "& p," << endl << flags_type << (he || ha || base_has_el || base_has_at ? " f" : "") << ")" << "{"; // Allow the base to parse its part. // if (base_has_el || base_has_at) os << "this->" << base << "::parse (p, f);" << endl; if (he || hae || mixed_p (c)) { bool m (mixed_p (c)); os << "for (; p.more_content (); p.next_content (" << (m ? "true" : "false") << "))" << "{"; if (m) { String const& ma (ctx.get ("mixed-aname")); String const& mi (ctx.get ("mixed-ordered-id-name")); String const& oa (ctx.get ("order-aname")); String const& ot (ctx.get ("order-type")); os << "if (p.cur_is_text ())" << "{" << "const " << xerces_ns << "::DOMText& t (" << "p.cur_text ());" << "this->" << ma << " ().push_back (" << endl << "::xsd::cxx::xml::transcode< " << char_type << " > (" << "t.getData (), t.getLength ()));" << "this->" << oa << " ().push_back (" << endl << ot << " (" << mi << "," << endl << "this->" << ma << " ().size () - 1));" << "continue;" << "}"; } if (he || hae) { os << "const " << xerces_ns << "::DOMElement& i (" << "p.cur_element ());" << "const " << qname_type << " n (" << endl << "::xsd::cxx::xml::dom::name< " << char_type << " > (i));" << endl; names (c, names_element_); } os << "break;" << "}"; // Make sure all non-optional elements are set. // names (c, names_element_test_); } if (ha || (haa && gen_wildcard)) { if (base_has_at) os << "p.reset_attributes ();" << endl; os << "while (p.more_attributes ())" << "{" << "const " << xerces_ns << "::DOMAttr& i (" << "p.next_attribute ());" << "const " << qname_type << " n (" << endl << "::xsd::cxx::xml::dom::name< " << char_type << " > (i));" << endl; names (c, names_attribute_); // Generate anyAttribute code after all the attributes. // if (gen_wildcard) names (c, names_any_attribute_); // os << "{" // else block // @@ // This doesn't play well with inheritance because we // don't expect base's attributes. Also there are other // "special" attributes such as xmlns, etc. // // << "throw ::xsd::cxx::tree::unexpected_attribute ... " // << "}"; os << "}"; // while loop // Make sure all non-optional attributes are set. // names (c, names_attribute_test_); } os << "}"; } } // _clone // if (!(c.abstract_p () || (renamed && polymorphic && polymorphic_p (c)))) os << name << "* " << name << "::" << endl << "_clone (" << flags_type << " f," << endl << container << "* c) const" << "{" << "return new class " << name << " (*this, f, c);" << "}"; // operator= // if (!options.suppress_assignment () && (he || ha || (gen_wildcard && (hae || haa)))) { os << name << "& " << name << "::" << endl << "operator= (const " << name << "& x)" << "{" << "if (this != &x)" << "{" << "static_cast< " << base << "& > (*this) = x;"; // Note that here we don't assign the DOMDocument that is // used to hold wildcard fragments. Each document has its // own copy. // Mixed text content. // if (mixed) { String const& m (ctx.get ("mixed-member")); os << "this->" << m << " = x." << m << ";"; } // Order container. // if (ordered) { String const& m (ctx.get ("order-member")); os << "this->" << m << " = x." << m << ";"; } names (c, assign_names_); os << "}" << "return *this;" << "}"; } // d-tor // os << name << "::" << endl << "~" << name << " ()" << "{" << "}"; // Register with type factory map. // if (polymorphic && polymorphic_p (c) && !c.abstract_p ()) { // Note that we are using the original type name. // String const& name (ename (c)); // If this type is anonymous but substitutes, then it will // be registered as part of the substitution registration. // if (!anonymous_p (c) && !options.suppress_parsing ()) { os << "static" << endl << "const ::xsd::cxx::tree::type_factory_initializer< " << poly_plate << ", " << char_type << ", " << name << " >" << endl << "_xsd_" << name << "_type_factory_init (" << endl << strlit (c.name ()) << "," << endl << strlit (xml_ns_name (c)) << ");" << endl; } if ((!anonymous_p (c) || anonymous_substitutes_p (c)) && options.generate_comparison ()) { os << "static" << endl << "const ::xsd::cxx::tree::comparison_initializer< " << poly_plate << ", " << char_type << ", " << name << " >" << endl << "_xsd_" << name << "_comparison_init;" << endl; } } // Comparison operators. // if (options.generate_comparison () && (he || ha || mixed || ordered || !c.inherits_p () || ((hae || haa) && gen_wildcard))) { bool base_comp (false); if (c.inherits_p ()) { HasComparisonOperator test (*this, base_comp); test.dispatch (c.inherits ().base ()); } bool has_body (he || ha || ordered || mixed || base_comp || ((hae || haa) && gen_wildcard)); os << "bool" << endl << "operator== (const " << name << "&" << (has_body ? " x" : "") << ", " << "const " << name << "&" << (has_body ? " y" : "") << ")" << "{"; if (base_comp) os << "if (!(static_cast< const " << base << "& > (x) ==" << endl << "static_cast< const " << base << "& > (y)))" << endl << "return false;" << endl; { Complex::names (c, comparison_names_); } if (mixed) { String const& an (ctx.get ("mixed-aname")); os << "if (!(x." << an << " () == y." << an << " ()))" << endl << "return false;" << endl; } if (ordered) { String const& an (ctx.get ("order-aname")); os << "if (!(x." << an << " () == y." << an << " ()))" << endl << "return false;" << endl; } os << "return true;" << "}"; os << "bool" << endl << "operator!= (const " << name << "& x, " << "const " << name << "& y)" << "{" << "return !(x == y);" << "}"; } } private: Traversal::Inherits inherits_member_; MemberTypeName member_name_; Traversal::Names names_element_; Traversal::Names names_element_test_; Traversal::Names names_attribute_; Traversal::Names names_any_attribute_; Traversal::Names names_attribute_test_; Any any_; Element element_; AnyTest any_test_; ElementTest element_test_; Attribute attribute_; AttributeTest attribute_test_; AnyAttribute any_attribute_; DefaultCtorAnyInit default_ctor_any_init_; DefaultCtorMemberInit default_ctor_member_init_; Traversal::Names default_ctor_init_names_; CtorAny ctor_any_; CtorMember ctor_member_; Traversal::Names ctor_names_; ElementCtorAny element_ctor_any_; ElementCtorMember element_ctor_member_; Traversal::Names element_ctor_names_; AssignAny assign_any_; AssignMember assign_member_; Traversal::Names assign_names_; AnyComparison comparison_any_; MemberComparison comparison_member_; Traversal::Names comparison_names_; FacetArray facet_array_; }; // Generate element types and substitution group map entries. // struct GlobalElement: Traversal::Element, GlobalElementBase, Context { GlobalElement (Context& c) : GlobalElementBase (c), Context (c), element_type_ (c.options.generate_element_type ()), element_map_ (c.options.generate_element_map ()), type_name_ (c) { belongs_ >> type_name_; } virtual void traverse (Type& e) { SemanticGraph::Type& t (e.type ()); // Check if this element is abstract. // bool abst; { SemanticGraph::Complex* tc; abst = (tc = dynamic_cast (&t)) != 0 && tc->abstract_p (); } if (!abst && element_type_ && doc_root_p (e)) { bool fund (false); { IsFundamentalType test (fund); test.dispatch (t); } bool simple (true); if (!fund) { IsSimpleType test (simple); test.dispatch (t); } String const& name (ename (e)); String const& type (etype (e)); String const& member (emember (e)); os << "// " << name << endl << "// " << endl << endl; // Virtual accessors. // os << "const " << any_type << "* " << name << "::" << endl << "_value () const" << "{"; if (fund) os << "return 0;"; else os << "return &this->" << member << ".get ();"; os << "}"; os << any_type << "* " << name << "::" << endl << "_value ()" << "{"; if (fund) os << "return 0;"; else os << "return &this->" << member << ".get ();"; os << "}"; // default c-tor // if (options.generate_default_ctor ()) { os << name << "::" << endl << name << " ()" << endl << ": " << member << " (0)" << "{" << "}"; } // c-tor (value) // os << name << "::" << endl << name << " (const " << type << "& x)" << endl << ": " << member << " (x, 0)" << "{" << "}"; // c-tor (auto_ptr) // if (!simple || (polymorphic && polymorphic_p (t))) { os << name << "::" << endl << name << " (" << auto_ptr << "< " << type << " > p)" << endl << ": " << member << " (" << (std >= cxx_version::cxx11 ? "::std::move (p)" : "p") << ", 0)" << "{" << "}"; } // c-tor (xercesc::DOMElement) // SemanticGraph::Context& ec (e.context ()); String const& name_member (ec.get ("element-name-member")); String const& ns_member (ec.get ("element-ns-member")); bool parsing (!options.suppress_parsing ()); if (parsing) { String const& tr (etraits (e)); os << name << "::" << endl << name << " (const " << xerces_ns << "::DOMElement& e, " << flags_type << " f)" << endl << ": " << member << " (0)" << "{" << "const " << qname_type << " n (" << endl << "::xsd::cxx::xml::dom::name< " << char_type << " > (e));" << endl << "if (n.name () == " << name_member << " && " << "n.namespace_ () == " << ns_member << ")" << endl << "this->" << member << ".set (" << tr << "::create (e, f, 0));" << "else" << endl << "throw ::xsd::cxx::tree::unexpected_element < " << char_type << " > (" << endl << "n.name (), n.namespace_ ()," << endl << name_member << ", " << ns_member << ");" << "}"; } // copy c-tor // os << name << "::" << endl << name << " (const " << name << "& x, " << flags_type << " f)" << endl << ": " << element_type << " ()," << endl << " " << member << " (x." << member << ", f, 0)" << "{" << "}"; // _clone // os << name << "* " << name << "::" << endl << "_clone (" << flags_type << " f) const" << "{" << "return new class " << name << " (*this, f);" << "}"; // Element name and namespace accessors. // String const& aname (ec.get ("element-name")); String const& ans (ec.get ("element-ns")); os << "const " << string_type << "& " << name << "::" << endl << aname << " ()" << "{" << "return " << name_member << ";" << "}"; os << "const " << string_type << "& " << name << "::" << endl << ans << " ()" << "{" << "return " << ns_member << ";" << "}"; os << "const " << string_type << "& " << name << "::" << endl << "_name () const" << "{" << "return " << name_member << ";" << "}"; os << "const " << string_type << "& " << name << "::" << endl << "_namespace () const" << "{" << "return " << ns_member << ";" << "}"; os << "const " << string_type << " " << name << "::" << endl << name_member << " (" << strlit (e.name ()) << ");" << endl << "const " << string_type << " " << name << "::" << endl << ns_member << " (" << strlit (e.namespace_ ().name ()) << ");" << endl; // d-tor // os << name << "::" << endl << "~" << name << " ()" << "{" << "}"; // Element map registration. // if (element_map_ && parsing) { os << "static " << endl << "const ::xsd::cxx::tree::parser_init< " << name << ", " << char_type << ", " << any_type << " >" << endl << "_xsd_" << name << "_parser_init (" << name << "::" << aname << " (), " << name << "::" << ans << " ());" << endl; } } if (!abst && polymorphic && e.substitutes_p () && !options.suppress_parsing ()) { String const& name (ename (e)); Type& r (e.substitutes ().root ()); os << "static" << endl << "const ::xsd::cxx::tree::element_factory_initializer< " << poly_plate << ", " << char_type << ", "; belongs (e, belongs_); os << " >" << endl << "_xsd_" << name << "_element_factory_init (" << endl << strlit (r.name ()) << "," << endl << strlit (r.namespace_ ().name ()) << "," << endl << strlit (e.name ()) << "," << endl << strlit (e.namespace_ ().name ()) << ");" << endl << endl; } } private: bool element_type_; bool element_map_; Traversal::Belongs belongs_; MemberTypeName type_name_; }; } void generate_tree_source (Context& ctx, size_t first, size_t last) { if (ctx.options.generate_wildcard ()) { ctx.os << "#include " << endl << endl; } if (!ctx.options.suppress_parsing ()) ctx.os << "#include " << endl << endl; if (ctx.polymorphic) { bool parsing (!ctx.options.suppress_parsing ()); bool comparison (ctx.options.generate_comparison ()); if (parsing) ctx.os << "#include " << endl << endl; if (comparison) ctx.os << "#include " << endl << endl; if (parsing || comparison) { bool import_maps (ctx.options.import_maps ()); bool export_maps (ctx.options.export_maps ()); if (import_maps || export_maps) { ctx.os << "#ifndef XSD_NO_EXPORT" << endl << endl << "namespace xsd" << "{" << "namespace cxx" << "{" << "namespace tree" << "{" << "#ifdef _MSC_VER" << endl; if (parsing && export_maps) ctx.os << "template struct __declspec (dllexport) " << "type_factory_plate< " << ctx.poly_plate << ", " << ctx.char_type << " >;"; if (parsing && import_maps) ctx.os << "template struct __declspec (dllimport) " << "type_factory_plate< " << ctx.poly_plate << ", " << ctx.char_type << " >;"; if (comparison && export_maps) ctx.os << "template struct __declspec (dllexport) " << "comparison_plate< " << ctx.poly_plate << ", " << ctx.char_type << " >;"; if (comparison && import_maps) ctx.os << "template struct __declspec (dllimport) " << "comparison_plate< " << ctx.poly_plate << ", " << ctx.char_type << " >;"; ctx.os << "#elif defined(__GNUC__) && __GNUC__ >= 4" << endl; if (parsing) ctx.os << "template struct __attribute__ ((visibility(\"default\"))) " << "type_factory_plate< " << ctx.poly_plate << ", " << ctx.char_type << " >;"; if (comparison) ctx.os << "template struct __attribute__ ((visibility(\"default\"))) " << "comparison_plate< " << ctx.poly_plate << ", " << ctx.char_type << " >;"; ctx.os << "#elif defined(XSD_MAP_VISIBILITY)" << endl; if (parsing) ctx.os << "template struct XSD_MAP_VISIBILITY " << "type_factory_plate< " << ctx.poly_plate << ", " << ctx.char_type << " >;"; if (comparison) ctx.os << "template struct XSD_MAP_VISIBILITY " << "comparison_plate< " << ctx.poly_plate << ", " << ctx.char_type << " >;"; ctx.os << "#endif" << endl << "}" // tree << "}" // cxx << "}" // xsd << "#endif // XSD_NO_EXPORT" << endl << endl; } ctx.os << "namespace _xsd" << "{"; if (parsing) ctx.os << "static" << endl << "const ::xsd::cxx::tree::type_factory_plate< " << ctx.poly_plate << ", " << ctx.char_type << " >" << endl << "type_factory_plate_init;" << endl; if (comparison) ctx.os << "static" << endl << "const ::xsd::cxx::tree::comparison_plate< " << ctx.poly_plate << ", " << ctx.char_type << " >" << endl << "comparison_plate_init;" << endl; ctx.os << "}"; } } Traversal::Schema schema; Sources sources; Traversal::Names names_ns, names; Namespace ns (ctx, first, last); List list (ctx); Union union_ (ctx); Complex complex (ctx); Enumeration enumeration (ctx); GlobalElement element (ctx); schema >> sources >> schema; schema >> names_ns >> ns >> names; names >> list; names >> union_; names >> complex; names >> enumeration; names >> element; schema.dispatch (ctx.schema_root); } } }