From 884dea7531962b17ef843ac2175faa050e8b0758 Mon Sep 17 00:00:00 2001 From: Boris Kolpackov Date: Thu, 10 Apr 2014 12:57:06 +0200 Subject: Add support for ordered types, mixed content --- xsd/cxx/tree/elements.hxx | 71 +++++- xsd/cxx/tree/fundamental-header.hxx | 11 + xsd/cxx/tree/generator.cxx | 10 + xsd/cxx/tree/name-processor.cxx | 285 +++++++++++++++++++++++- xsd/cxx/tree/options.cli | 60 ++++++ xsd/cxx/tree/order-processor.cxx | 244 +++++++++++++++++++++ xsd/cxx/tree/order-processor.hxx | 30 +++ xsd/cxx/tree/polymorphism-processor.cxx | 64 +----- xsd/cxx/tree/serialization-source.cxx | 219 +++++++++++++++---- xsd/cxx/tree/tree-header.cxx | 369 ++++++++++++++++++++++++++++++-- xsd/cxx/tree/tree-inline.cxx | 74 ++++++- xsd/cxx/tree/tree-source.cxx | 251 ++++++++++++++++++++-- xsd/makefile | 2 + xsd/options-parser.hxx | 3 +- 14 files changed, 1550 insertions(+), 143 deletions(-) create mode 100644 xsd/cxx/tree/order-processor.cxx create mode 100644 xsd/cxx/tree/order-processor.hxx (limited to 'xsd') diff --git a/xsd/cxx/tree/elements.hxx b/xsd/cxx/tree/elements.hxx index f3f9f66..6874e6a 100644 --- a/xsd/cxx/tree/elements.hxx +++ b/xsd/cxx/tree/elements.hxx @@ -6,6 +6,7 @@ #define CXX_TREE_ELEMENTS_HXX #include +#include #include #include #include @@ -68,6 +69,54 @@ namespace CXX String reason_; }; + // A set of potentially qualified XML Schema type names. + // + struct TypeNameSet + { + template + TypeNameSet (I begin, I end) + { + for (; begin != end; ++begin) + insert (*begin); + } + + void + insert (String const& name) + { + size_t p (name.rfind ('#')); + + if (p == String::npos) + unames_.insert (name); + else + qnames_.insert (name); + } + + bool + find (SemanticGraph::Type& t) + { + if (!unames_.empty ()) + { + if (unames_.find (t.name ()) != unames_.end ()) + return true; + } + + if (!qnames_.empty ()) + { + if (qnames_.find (t.scope ().name () + L"#" + t.name ()) != + qnames_.end ()) + return true; + } + + return false; + } + + private: + typedef std::set StringSet; + + StringSet unames_; + StringSet qnames_; + }; + // // class Context: public CXX::Context @@ -157,6 +206,22 @@ namespace CXX // // public: + static bool + ordered_p (SemanticGraph::Type const& t) + { + return t.context ().count ("ordered") && + t.context ().get ("ordered"); + } + + // Check if we are generating mixed support for this type. We only + // do it for ordered types. + // + static bool + mixed_p (SemanticGraph::Complex const& c) + { + return c.mixed_p () && ordered_p (c); + } + bool polymorphic_p (SemanticGraph::Type&); @@ -1338,7 +1403,11 @@ namespace CXX virtual void traverse (SemanticGraph::Complex& c) { - names (c, names_); + if (c.mixed_p ()) + v_ = false; + + if (v_) + names (c, names_); if (v_) inherits (c, inherits_); diff --git a/xsd/cxx/tree/fundamental-header.hxx b/xsd/cxx/tree/fundamental-header.hxx index dbe7c9a..1145c0c 100644 --- a/xsd/cxx/tree/fundamental-header.hxx +++ b/xsd/cxx/tree/fundamental-header.hxx @@ -724,6 +724,17 @@ namespace CXX bool serialization (options.generate_serialization ()); bool element_map (options.generate_element_map ()); + { + if (doxygen) + os << endl + << "/**" << endl + << " * @brief Content order sequence entry." << endl + << " */" << endl; + + gen_typedef (c.get ("content-order"), + "::xsd::cxx::tree::content_order"); + } + if (options.generate_element_type ()) { if (doxygen) diff --git a/xsd/cxx/tree/generator.cxx b/xsd/cxx/tree/generator.cxx index 5178bb1..f7eb1fa 100644 --- a/xsd/cxx/tree/generator.cxx +++ b/xsd/cxx/tree/generator.cxx @@ -24,6 +24,7 @@ #include #include #include +#include #include #include @@ -234,6 +235,15 @@ namespace CXX bool gen_cxx (!ops.generate_dep_only ()); + // Process ordered types. + // + if (gen_cxx) + { + OrderProcessor proc; + if (!proc.process (ops, schema, file_path)) + throw Failed (); + } + // Process names. // if (gen_cxx) diff --git a/xsd/cxx/tree/name-processor.cxx b/xsd/cxx/tree/name-processor.cxx index e34ae84..1f3844b 100644 --- a/xsd/cxx/tree/name-processor.cxx +++ b/xsd/cxx/tree/name-processor.cxx @@ -60,6 +60,7 @@ namespace CXX seq_modifier_regex (seq_modifier_regex_), parser_regex (parser_regex_), serializer_regex (serializer_regex_), + const_regex (const_regex_), enumerator_regex (enumerator_regex_), element_type_regex (element_type_regex_) { @@ -231,6 +232,30 @@ namespace CXX "serializer"); } + // Const regex. + // + { + if (fn == "knr") + { + const_regex.push_back ("/([^,]+),([^,]+),([^,]+)/$1_$2_$3/"); + const_regex.push_back ("/([^,]+),([^,]+)/$1_$2/"); + } + else if (fn == "lcc") + { + const_regex.push_back ("/([^,]+),([^,]+),([^,]+)/\\l$1_\\u$2_\\u$3/"); + const_regex.push_back ("/([^,]+),([^,]+)/\\l$1\\u$2/"); + } + else + { + // Java: all uppercase. + // + const_regex.push_back ("/([^,]+),([^,]+),([^,]+)/\\U$1_$2_$3/"); + const_regex.push_back ("/([^,]+),([^,]+)/\\U$1_$2/"); + } + + compile_regex (options.const_regex (), const_regex, "const"); + } + // Enumerator name regex. // { @@ -267,6 +292,7 @@ namespace CXX seq_modifier_regex (c.seq_modifier_regex), parser_regex (c.parser_regex), serializer_regex (c.serializer_regex), + const_regex (c.const_regex), enumerator_regex (c.enumerator_regex), element_type_regex (c.element_type_regex) { @@ -522,6 +548,7 @@ namespace CXX RegexVector seq_modifier_regex_; RegexVector parser_regex_; RegexVector serializer_regex_; + RegexVector const_regex_; RegexVector enumerator_regex_; RegexVector element_type_regex_; @@ -542,6 +569,7 @@ namespace CXX RegexVector& seq_modifier_regex; RegexVector& parser_regex; RegexVector& serializer_regex; + RegexVector& const_regex; RegexVector& enumerator_regex; RegexVector& element_type_regex; }; @@ -655,6 +683,9 @@ namespace CXX if (Tree::Context::skip (m)) return; + SemanticGraph::Complex& c ( + dynamic_cast (m.scope ())); + size_t max (Tree::Context::max (m)); size_t min (Tree::Context::min (m)); @@ -662,7 +693,7 @@ namespace CXX String const& b (m.context ().get ("name")); bool def_attr (m.default_p () && - m.is_a ()); + m.is_a ()); // Accessors/modifiers. Note that we postpone inserting // the names into the name_set to avoid over-escaping. @@ -816,7 +847,7 @@ namespace CXX process_regex ( s + L",default,value", accessor_regex, L"accessor"))); - m.context ().set ( "default-value", find_name (an, name_set_)); + m.context ().set ("default-value", find_name (an, name_set_)); bool lit (false); { @@ -832,6 +863,18 @@ namespace CXX } } } + + // Element id. + // + if (m.is_a () && ordered_p (c)) + { + String id ( + escape ( + process_regex ( + s + L",id", const_regex, L"const"))); + + m.context ().set ("ordered-id-name", find_name (id, name_set_)); + } } private: @@ -857,6 +900,9 @@ namespace CXX virtual void traverse (SemanticGraph::Any& a) { + SemanticGraph::Complex& c ( + dynamic_cast (a.scope ())); + size_t max (Tree::Context::max (a)); size_t min (Tree::Context::min (a)); @@ -972,6 +1018,18 @@ namespace CXX // a.context ().set ("member", find_name (b + L"_", name_set_)); + // Wildcard id. + // + if (ordered_p (c)) + { + String id ( + escape ( + process_regex ( + s + L",id", const_regex, L"const"))); + + a.context ().set ("ordered-id-name", find_name (id, name_set_)); + } + if (!has_wildcard_) has_wildcard_ = true; } @@ -1057,17 +1115,17 @@ namespace CXX virtual void traverse (Type& c) { - SemanticGraph::Context& cc (c.context ()); + SemanticGraph::Context& ctx (c.context ()); // We leave this set around to allow other mappings to use // this information. // - cc.set ("cxx-tree-name-processor-stem-set", NameSet ()); - cc.set ("cxx-tree-name-processor-member-set", NameSet ()); + ctx.set ("cxx-tree-name-processor-stem-set", NameSet ()); + ctx.set ("cxx-tree-name-processor-member-set", NameSet ()); // Use processed name. // - String name (cc.get ("name")); + String name (ctx.get ("name")); // If renamed name is empty then we are not generating // anything for this type and name processing is not @@ -1077,10 +1135,10 @@ namespace CXX return; NameSet& stem_set ( - cc.get ("cxx-tree-name-processor-stem-set")); + ctx.get ("cxx-tree-name-processor-stem-set")); NameSet& member_set ( - cc.get ("cxx-tree-name-processor-member-set")); + ctx.get ("cxx-tree-name-processor-member-set")); stem_set.insert (c.name ()); member_set.insert (name); @@ -1136,6 +1194,116 @@ namespace CXX Complex::names (c, names); } + // Names for the mixed content. + // + if (mixed_p (c)) + { + // Check if we already have the mixed content down inheritance + // hierarchy. + // + using SemanticGraph::Complex; + + for (Complex* p (&c); p->inherits_p ();) + { + if (Complex* b = dynamic_cast ( + &p->inherits ().base ())) + { + if (mixed_p (*b)) + { + SemanticGraph::Context& bctx (b->context ()); + ctx.set ("mixed-type", bctx.get ("mixed-type")); + ctx.set ("mixed-const-iterator", + bctx.get ("mixed-const-iterator")); + ctx.set ("mixed-ordered-id-name", + bctx.get ("mixed-ordered-id-name")); + ctx.set ("mixed-aname", bctx.get ("mixed-aname")); + ctx.set ("mixed-member", bctx.get ("mixed-member")); + ctx.set ("mixed-in-base", true); + break; + } + + p = b; + } + else + break; + } + + // If not, set up the names. + // + if (!ctx.count ("mixed-in-base")) + { + String s (find_name (L"text,content", stem_set)); + String n (find_name (escape (s), member_set, false)); + + String an (find_name ( + escape (process_regex (s, + seq_accessor_regex, + accessor_regex, + L"sequence accessor")), + member_set, + false)); + + String mn (find_name ( + escape (process_regex (s, + seq_modifier_regex, + modifier_regex, + L"sequence modifier")), + member_set, + false)); + + ctx.set ("mixed-aname", an); + ctx.set ("mixed-mname", mn); + + member_set.insert (name); + + if (an != n) + member_set.insert (an); + + if (mn != n && mn != an) + member_set.insert (mn); + + // Types. + // + ctx.set ( + "mixed-type", + find_name ( + escape (process_regex (s + L",type", type_regex, L"type")), + member_set)); + + ctx.set ( + "mixed-container", + find_name ( + escape (process_regex (s + L",sequence", type_regex, L"type")), + member_set)); + + ctx.set ( + "mixed-iterator", + find_name ( + escape (process_regex (s + L",iterator", type_regex, L"type")), + member_set)); + + ctx.set ( + "mixed-const-iterator", + find_name ( + escape ( + process_regex (s + L",const,iterator", type_regex, L"type")), + member_set)); + + // Text content id. + // + ctx.set ( + "mixed-ordered-id-name", + find_name ( + escape ( + process_regex (s + L",id", const_regex, L"const")), + member_set)); + + // Data member. + // + ctx.set ("mixed-member", find_name (n + L"_", member_set)); + } + } + // Names for wildcards. // if (options.generate_wildcard ()) @@ -1190,6 +1358,105 @@ namespace CXX } } } + + // Names for the order container. + // + if (ordered_p (c)) + { + // Check if we already have the order container down + // inheritance hierarchy. + // + using SemanticGraph::Complex; + + for (Complex* p (&c); p->inherits_p ();) + { + if (Complex* b = dynamic_cast ( + &p->inherits ().base ())) + { + if (ordered_p (*b)) + { + SemanticGraph::Context& bctx (b->context ()); + ctx.set ("order-type", bctx.get ("order-type")); + ctx.set ("order-const-iterator", + bctx.get ("order-const-iterator")); + ctx.set ("order-aname", bctx.get ("order-aname")); + ctx.set ("order-member", bctx.get ("order-member")); + ctx.set ("order-in-base", true); + break; + } + + p = b; + } + else + break; + } + + // If not, set up the names. + // + if (!ctx.count ("order-in-base")) + { + String s (find_name (L"content,order", stem_set)); + String n (find_name (escape (s), member_set, false)); + + String an (find_name ( + escape (process_regex (s, + seq_accessor_regex, + accessor_regex, + L"sequence accessor")), + member_set, + false)); + + String mn (find_name ( + escape (process_regex (s, + seq_modifier_regex, + modifier_regex, + L"sequence modifier")), + member_set, + false)); + + ctx.set ("order-aname", an); + ctx.set ("order-mname", mn); + + member_set.insert (name); + + if (an != n) + member_set.insert (an); + + if (mn != n && mn != an) + member_set.insert (mn); + + // Types. + // + ctx.set ( + "order-type", + find_name ( + escape (process_regex (s + L",type", type_regex, L"type")), + member_set)); + + ctx.set ( + "order-container", + find_name ( + escape (process_regex (s + L",sequence", type_regex, L"type")), + member_set)); + + ctx.set ( + "order-iterator", + find_name ( + escape (process_regex (s + L",iterator", type_regex, L"type")), + member_set)); + + ctx.set ( + "order-const-iterator", + find_name ( + escape ( + process_regex (s + L",const,iterator", type_regex, L"type")), + member_set)); + + // Data member. + // + ctx.set ("order-member", find_name (n + L"_", member_set)); + } + } } }; @@ -1870,6 +2137,8 @@ namespace CXX process_name (n, "buffer", "buffer"); process_name (n, "time,zone", "time-zone"); + process_name (n, "content,order", "content-order"); + if (options.generate_element_type ()) process_name (n, "element,type", "element-type"); diff --git a/xsd/cxx/tree/options.cli b/xsd/cxx/tree/options.cli index ac126fe..026e4a1 100644 --- a/xsd/cxx/tree/options.cli +++ b/xsd/cxx/tree/options.cli @@ -51,6 +51,58 @@ namespace CXX schemas that define the same polymorphic types." }; + // Ordered content. + // + NarrowStrings --ordered-type + { + "", + "Indicate that element order in is significant. An example + would be a complex type with unbounded choice as a content model + where the element order in XML has application-specific semantics. + For ordered types the compiler generates a special container data + member and a corresponding set of accessors and modifiers that are + used to capture the order of elements and, for mixed content, of + text. + + The argument is an XML Schema type name that can be optionally + qualified with a namespace in the \c{\i{namespace}\b{#}\i{name}} form. + Note also that you will need to specify this option when compiling + every schema file that has other ordered types derived from this + type." + }; + + bool --ordered-type-derived + { + "Automatically treat types derived from ordered bases as also + ordered. This is primarily useful if you would like to be able + to iterate over the complete content using the content order + container." + }; + + bool --ordered-type-mixed + { + "Automatically treat complex types with mixed content as ordered." + }; + + bool --ordered-type-all + { + "Indicate that element order in all types is significant." + }; + + NarrowString --order-container + { + "", + "Specify a custom class template that should be used as a container + for the content order in ordered types instead of the default + \cb{std::vector}. See \cb{--ordered-type} for more information on + ordered type. This option is primarily useful if you need to + perform more complex lookups in the content order container, for + example by element id. In this case, a container like Boost + multi-index may be more convenient. Note that if using a custom + container, you will also most likely need to include the relevant + headers using the \cb{--hxx-prologue*} options." + }; + // Features. // bool --generate-serialization @@ -299,6 +351,14 @@ namespace CXX the NAMING CONVENTION section below for more information." }; + NarrowStrings --const-regex + { + "", + "Add to the list of regular expressions used to translate + XML Schema-derived names to C++ constant names. See the NAMING + CONVENTION section below for more information." + }; + NarrowStrings --enumerator-regex { "", diff --git a/xsd/cxx/tree/order-processor.cxx b/xsd/cxx/tree/order-processor.cxx new file mode 100644 index 0000000..68eee8c --- /dev/null +++ b/xsd/cxx/tree/order-processor.cxx @@ -0,0 +1,244 @@ +// file : xsde/cxx/tree/order-processor.cxx +// copyright : Copyright (c) 2006-2014 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#include + +#include +#include + +#include +#include + +using namespace std; + +namespace CXX +{ + namespace Tree + { + namespace + { + struct Member: Traversal::Element, Traversal::Any + { + Member (size_t count): count_ (count) {} + + virtual void + traverse (SemanticGraph::Element& e) + { + if (Context::skip (e)) + return; + + e.context ().set ("ordered-id", count_++); + } + + virtual void + traverse (SemanticGraph::Any& a) + { + a.context ().set ("ordered-id", count_++); + } + + size_t count_; + }; + + // + // + struct Type: Traversal::Complex + { + Type (TypeNameSet& ordered_types, bool derived, bool mixed, bool all) + : ordered_types_ (ordered_types), + derived_ (derived), + mixed_ (mixed), + all_ (all) + { + } + + virtual void + traverse (SemanticGraph::Complex& c) + { + SemanticGraph::Context& ctx (c.context ()); + + if (!ctx.count ("ordered")) + { + // First process our base. + // + if (c.inherits_p ()) + { + SemanticGraph::Type& b (c.inherits ().base ()); + + if (!b.context ().count ("ordered")) + dispatch (b); + } + + // See if our base (not necessarily immediate) is ordered. + // + using SemanticGraph::Complex; + + Complex* b (0); + + for (Complex* p (&c); p->inherits_p ();) + { + if ((b = dynamic_cast (&p->inherits ().base ()))) + { + if (Context::ordered_p (*b)) + break; + + p = b; + } + else + break; + } + + bool o (all_ || + (derived_ && b != 0 && Context::ordered_p (*b)) || + (mixed_ && c.mixed_p ()) || + ordered_types_.find (c)); + ctx.set ("ordered", o); + + // Assign ids to elements and wildcards, calculate total count. + // + if (o) + { + size_t count ( + b != 0 && Context::ordered_p (*b) + ? b->context ().get ("ordered-count") + : 1); + + ctx.set ("ordered-start", count); + + Member m (count); + Traversal::Names n (m); + names (c, n); + + // Assign content id for mixed text. + // + if (Context::mixed_p (c) && count == 1) + ctx.set ("mixed-ordered-id", m.count_++); + + ctx.set ("ordered-count", m.count_); + } + } + } + + private: + TypeNameSet& ordered_types_; + bool derived_; + bool mixed_; + bool all_; + }; + + // Go into sourced/included/imported schemas while making sure + // we don't process the same stuff more than once. + // + struct Uses: Traversal::Sources, + Traversal::Includes, + Traversal::Imports + { + Uses (char const* seen_key) + : seen_key_ (seen_key) + { + } + + virtual void + traverse (SemanticGraph::Sources& sr) + { + SemanticGraph::Schema& s (sr.schema ()); + + if (!s.context ().count (seen_key_)) + { + s.context ().set (seen_key_, true); + Traversal::Sources::traverse (sr); + } + } + + virtual void + traverse (SemanticGraph::Includes& i) + { + SemanticGraph::Schema& s (i.schema ()); + + if (!s.context ().count (seen_key_)) + { + s.context ().set (seen_key_, true); + Traversal::Includes::traverse (i); + } + } + + virtual void + traverse (SemanticGraph::Imports& i) + { + SemanticGraph::Schema& s (i.schema ()); + + if (!s.context ().count (seen_key_)) + { + s.context ().set (seen_key_, true); + Traversal::Imports::traverse (i); + } + } + + private: + char const* seen_key_; + }; + + char const* seen_key = "cxx-tree-order-processor-seen"; + + bool + process_impl (options const& ops, + SemanticGraph::Schema& tu, + SemanticGraph::Path const&) + { + // Prepare a set of ordered types. + // + TypeNameSet ordered_types (ops.ordered_type ().begin (), + ops.ordered_type ().end ()); + + // Root schema in the file-per-type mode is just a bunch + // of includes without a namespace. + // + SemanticGraph::Schema::NamesIterator i (tu.names_begin ()); + + // Nothing to do if this is the XML Schema namespace. + // + if (i == tu.names_end () || + i->named ().name () != L"http://www.w3.org/2001/XMLSchema") + { + // Note that we check first if this schema has already been + // processed which may happen in the file-per-type compilation + // mode. + // + if (!tu.context ().count (seen_key)) + { + Traversal::Schema schema; + Uses uses (seen_key); + + schema >> uses >> schema; + + Traversal::Names schema_names; + Traversal::Namespace ns; + Traversal::Names ns_names; + Type type (ordered_types, + ops.ordered_type_derived (), + ops.ordered_type_mixed (), + ops.ordered_type_all ()); + + schema >> schema_names >> ns >> ns_names >> type; + + // Some twisted schemas do recusive self-inclusion. + // + tu.context ().set (seen_key, true); + + schema.dispatch (tu); + } + } + + return true; + } + } + + bool OrderProcessor:: + process (options const& ops, + SemanticGraph::Schema& tu, + SemanticGraph::Path const& file) + { + return process_impl (ops, tu, file); + } + } +} diff --git a/xsd/cxx/tree/order-processor.hxx b/xsd/cxx/tree/order-processor.hxx new file mode 100644 index 0000000..fa68d21 --- /dev/null +++ b/xsd/cxx/tree/order-processor.hxx @@ -0,0 +1,30 @@ +// file : xsde/cxx/tree/order-processor.hxx +// copyright : Copyright (c) 2006-2014 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#ifndef CXX_TREE_ORDER_PROCESSOR_HXX +#define CXX_TREE_ORDER_PROCESSOR_HXX + +#include + +#include +#include + +#include + +namespace CXX +{ + namespace Tree + { + class OrderProcessor + { + public: + bool + process (options const&, + XSDFrontend::SemanticGraph::Schema&, + XSDFrontend::SemanticGraph::Path const& file); + }; + } +} + +#endif // CXX_TREE_ORDER_PROCESSOR_HXX diff --git a/xsd/cxx/tree/polymorphism-processor.cxx b/xsd/cxx/tree/polymorphism-processor.cxx index fb96ba7..cbd2471 100644 --- a/xsd/cxx/tree/polymorphism-processor.cxx +++ b/xsd/cxx/tree/polymorphism-processor.cxx @@ -2,7 +2,6 @@ // copyright : Copyright (c) 2006-2014 Code Synthesis Tools CC // license : GNU GPL v2 + exceptions; see accompanying LICENSE file -#include #include #include @@ -19,59 +18,12 @@ namespace CXX { namespace { - struct TypeSet - { - template - TypeSet (I begin, I end) - { - for (; begin != end; ++begin) - insert (*begin); - } - - void - insert (String const& name) - { - size_t p (name.rfind ('#')); - - if (p == String::npos) - unames_.insert (name); - else - qnames_.insert (name); - } - - bool - find (SemanticGraph::Type& t) - { - if (!unames_.empty ()) - { - if (unames_.find (t.name ()) != unames_.end ()) - return true; - } - - if (!qnames_.empty ()) - { - if (qnames_.find (t.scope ().name () + L"#" + t.name ()) != - qnames_.end ()) - return true; - } - - return false; - } - - private: - typedef set StringSet; - - StringSet unames_; - StringSet qnames_; - }; - - // // struct Type: Traversal::Type, Traversal::Complex { - Type (TypeSet& poly_types) + Type (TypeNameSet& poly_types) : poly_types_ (poly_types) { } @@ -110,7 +62,7 @@ namespace CXX } private: - TypeSet& poly_types_; + TypeNameSet& poly_types_; }; struct FundType: Traversal::AnyType, @@ -169,7 +121,7 @@ namespace CXX Traversal::Fundamental::Entity, Traversal::Fundamental::Entities { - FundType (TypeSet& poly_types, bool& valid) + FundType (TypeNameSet& poly_types, bool& valid) : poly_types_ (poly_types), valid_ (valid) { } @@ -493,13 +445,13 @@ namespace CXX } private: - TypeSet& poly_types_; + TypeNameSet& poly_types_; bool& valid_; }; struct GlobalElement: Traversal::Element { - GlobalElement (TypeSet& poly_types, + GlobalElement (TypeNameSet& poly_types, bool& valid, const WarningSet& disabled_warnings) : poly_types_ (poly_types), valid_ (valid), warning_ (true) @@ -603,7 +555,7 @@ namespace CXX } private: - TypeSet& poly_types_; + TypeNameSet& poly_types_; bool& valid_; bool warning_; }; @@ -674,8 +626,8 @@ namespace CXX // Prepare a set of polymorphic types. // - TypeSet poly_types (ops.polymorphic_type ().begin (), - ops.polymorphic_type ().end ()); + TypeNameSet poly_types (ops.polymorphic_type ().begin (), + ops.polymorphic_type ().end ()); // Root schema in the file-per-type mode is just a bunch // of includes without a namespace. diff --git a/xsd/cxx/tree/serialization-source.cxx b/xsd/cxx/tree/serialization-source.cxx index 8cb3463..559a3cf 100644 --- a/xsd/cxx/tree/serialization-source.cxx +++ b/xsd/cxx/tree/serialization-source.cxx @@ -295,6 +295,11 @@ namespace CXX if (skip (e)) return; + SemanticGraph::Complex& c ( + dynamic_cast (e.scope ())); + + bool ordered (ordered_p (c)); + String const& aname (eaname (e)); String ns (e.qualified_p () ? e.namespace_ ().name () : ""); String type (scope + L"::" + etype (e)); @@ -311,9 +316,14 @@ namespace CXX os << "// " << comment (e.name ()) << endl << "//" << endl; + if (ordered) + os << "case " << scope << "::" << + e.context ().get ("ordered-id-name") << ":" + << "{"; + if (poly) { - os << "{" + os << (ordered ? "" : "{") << "::xsd::cxx::tree::type_serializer_map< " << char_type << " >& tsm (" << endl << "::xsd::cxx::tree::type_serializer_map_instance< " << @@ -325,15 +335,22 @@ namespace CXX { // sequence // - os << "for (" << scope << "::" << econst_iterator (e) << endl - << "b (i." << aname << " ().begin ()), " << - "n (i." << aname << " ().end ());" << endl - << "b != n; ++b)" - << "{"; + if (ordered) + os << "const " << type << "& x (i." << aname << + " ()[b->index]);" + << endl; + else + os << "for (" << scope << "::" << econst_iterator (e) << endl + << "b (i." << aname << " ().begin ()), " << + "n (i." << aname << " ().end ());" << endl + << "b != n; ++b)" + << "{"; + + char const* x (ordered ? "x" : "*b"); if (poly) { - os << "if (typeid (" << type << ") == typeid (*b))" + os << "if (typeid (" << type << ") == typeid (" << x << "))" << "{" << xerces_ns << "::DOMElement& s (" << endl << "::xsd::cxx::xml::dom::create_element (" << endl @@ -341,14 +358,14 @@ namespace CXX << (ns ? strlit (ns) + L",\n" : L"") << "e));" << endl - << "s << *b;" + << "s << " << x << ";" << "}" << "else" << endl << "tsm.serialize (" << endl << strlit (e.name ()) << "," << endl << strlit (ns) << "," << endl << (e.global_p () ? "true" : "false") << ", " << - (e.qualified_p () ? "true" : "false") << ", e, *b);"; + (e.qualified_p () ? "true" : "false") << ", e, " << x << ");"; } else { @@ -363,30 +380,29 @@ namespace CXX { case st_other: { - os << "s << *b;"; + os << "s << " << x << ";"; break; } case st_double: { - os << "s << " << as_double_type << " (*b);"; + os << "s << " << as_double_type << " (" << x << ");"; break; } case st_decimal: { - os << "s << " << as_decimal_type << " (*b);"; + os << "s << " << as_decimal_type << " (" << x << ");"; break; } } } - - os << "}"; } else if (min (e) == 0) { // optional // - os << "if (i." << aname << " ())" - << "{"; + if (!ordered) + os << "if (i." << aname << " ())" + << "{"; if (poly) { @@ -436,8 +452,6 @@ namespace CXX } } } - - os << "}"; } else { @@ -465,8 +479,10 @@ namespace CXX } else { - os << "{" - << xerces_ns << "::DOMElement& s (" << endl + if (!ordered) + os << "{"; + + os << xerces_ns << "::DOMElement& s (" << endl << "::xsd::cxx::xml::dom::create_element (" << endl << strlit (e.name ()) << "," << endl << (ns ? strlit (ns) + L",\n" : L"") @@ -491,13 +507,26 @@ namespace CXX break; } } - - os << "}"; } } - if (poly) + if (ordered) + { + // See comment for bool text (false); below. + // + if (mixed_p (c) && c.context ().get ("ordered-start") != 1) + os << "text = true;"; + + os << "continue;" + << "}"; + } + else + { os << "}"; + + if (poly && (max (e) != 1 || min (e) == 0)) + os << "}"; // There is no extra block for poly one. + } } private: @@ -514,48 +543,77 @@ namespace CXX virtual void traverse (Type& a) { + SemanticGraph::Complex& c ( + dynamic_cast (a.scope ())); + + bool ordered (ordered_p (c)); + String const& aname (eaname (a)); os << "// " << ename (a) << endl << "//" << endl; + if (ordered) + os << "case " << scope << "::" << + a.context ().get ("ordered-id-name") << ":"; + if (max (a) != 1) { // sequence // - os << "for (" << scope << "::" << econst_iterator (a) << endl - << "b (i." << aname << " ().begin ()), " << - "n (i." << aname << " ().end ());" << endl - << "b != n; ++b)" - << "{" + if (!ordered) + os << "for (" << scope << "::" << econst_iterator (a) << endl + << "b (i." << aname << " ().begin ()), " << + "n (i." << aname << " ().end ());" << endl + << "b != n; ++b)"; + + os << "{" << "e.appendChild (" << endl << "e.getOwnerDocument ()->importNode (" << endl << "const_cast< " << xerces_ns << - "::DOMElement* > (&(*b)), true));" - << "}"; + "::DOMElement* > (&(" << + (ordered ? (L"i." + aname + L" ()[b->index]") : L"*b") << + ")), true));"; } else if (min (a) == 0) { // optional // - os << "if (i." << aname << " ())" - << "{" + if (!ordered) + os << "if (i." << aname << " ())"; + + os << "{" << "e.appendChild (" << endl << "e.getOwnerDocument ()->importNode (" << endl << "const_cast< " << xerces_ns << "::DOMElement* > (&(*i." << - aname << " ())), true));" - << "}"; + aname << " ())), true));"; } else { // one // + if (ordered) + os << "{"; + os << "e.appendChild (" << endl << "e.getOwnerDocument ()->importNode (" << endl << "const_cast< " << xerces_ns << "::DOMElement* > (&(i." << aname << " ())), true));" << endl; } + + if (ordered) + { + // See comment for bool text (false); below. + // + if (mixed_p (c) && c.context ().get ("ordered-start") != 1) + os << "text = true;"; + + os << "continue;"; + } + + if (ordered || max (a) != 1 || min (a) == 0) + os << "}"; } private: @@ -702,6 +760,8 @@ namespace CXX virtual void traverse (Type& c) { + SemanticGraph::Context& ctx (c.context ()); + String name (ename (c)); // If renamed name is empty then we do not need to generate @@ -740,22 +800,107 @@ namespace CXX } { + bool o (ordered_p (c)); + size_t start, count; + + if (o) + { + start = ctx.get ("ordered-start"); + count = ctx.get ("ordered-count"); + + if (start != count) + { + String const& ci (ctx.get ("order-const-iterator")); + String const& an (ctx.get ("order-aname")); + + // If we have mixed content and a base, then we have to + // skip the text content until we serialize one of "our" + // elements. + // + if (mixed_p (c) && start != 1) + os << "bool text (false);" + << endl; + + os << "for (" << name << "::" << ci << endl + << "b (i." << an << " ().begin ()), n (i." << an << + " ().end ());" << endl + << "b != n; ++b)" + << "{" + << "switch (b->id)" + << "{"; + } + } + Traversal::Names names; Any any (*this, name); Element element (*this, name); - Attribute attribute (*this, name); names >> element; - names >> attribute; if (options.generate_wildcard ()) names >> any; Complex::names (c, names); + + if (o) + { + if (start != count) + { + if (mixed_p (c)) + { + //@@ propagate mixed-ordered-id to derived + + os << "// text_content" << endl + << "//" << endl + << "case " << name << "::" << + ctx.get ("mixed-ordered-id-name") << ":" + << "{"; + + // See the comment above. + // + if (start != 1) + os << "if (text)" << endl; + + os << "e.appendChild (" << endl + << "e.getOwnerDocument ()->createTextNode (" << endl + << "::xsd::cxx::xml::string (" << endl + << "i." << ctx.get ("mixed-aname") << + " ()[b->index].c_str ()).c_str ()));"; + + // os << "e << i." << ctx.get ("mixed-aname") << + // " ()[b->index];"; + + os << "continue;" + << "}"; + } + + // Ignore content before our id range and stop serializing + // if we see anything past. This handles inheritance. + // + os << "default:" + << "{"; + + if (start != 1) + os << "if (b->id < " << start << "UL)" << endl + << "continue;"; + + os << "break;" // Stop (see break below). + << "}"; + + os << "}" // switch + << "break;" // Unknown element past our elements. + << "}"; // for + } + } } - os << "}"; + { + Attribute attribute (*this, name); + Traversal::Names names (attribute); + Complex::names (c, names); + } + os << "}"; bool simple (true); { diff --git a/xsd/cxx/tree/tree-header.cxx b/xsd/cxx/tree/tree-header.cxx index 83a2d1f..e6c2411 100644 --- a/xsd/cxx/tree/tree-header.cxx +++ b/xsd/cxx/tree/tree-header.cxx @@ -1076,7 +1076,7 @@ namespace CXX } bool def_attr (m.default_p () && - m.is_a ()); + m.is_a ()); if (max (m) != 1) { @@ -1784,6 +1784,9 @@ namespace CXX if (skip (m)) return; + SemanticGraph::Complex& c ( + dynamic_cast (m.scope ())); + String const& type (etype (m)); bool el (m.is_a ()); @@ -1826,7 +1829,7 @@ namespace CXX else { os << "// " << comment (m.name ()) << endl - << "// " << endl; + << "//" << endl; } // Typedefs. @@ -1872,7 +1875,7 @@ namespace CXX << " */" << endl; } - // IntelliSense does not not like aliases and fully-qualified + // IntelliSense does not like aliases and fully-qualified // names here. // if (!isense) @@ -1941,6 +1944,24 @@ namespace CXX os << " > " << etraits (m) << ";" << endl; + + // Element id. + // + if (el && ordered_p (c)) + { + if (doxygen) + os << "/**" << endl + << " * @brief Element id used for capturing content " << + "order." << endl + << " */" << endl; + + SemanticGraph::Context& ctx (m.context ()); + + os << "static const ::std::size_t " << + ctx.get ("ordered-id-name") << " = " << + ctx.get ("ordered-id") << "UL;" << endl; + } + member_function_.traverse (m); if (doxygen) @@ -1970,6 +1991,9 @@ namespace CXX virtual void traverse (SemanticGraph::Any& a) { + SemanticGraph::Complex& c ( + dynamic_cast (a.scope ())); + if (doxygen) { os << "/**" << endl @@ -1990,7 +2014,7 @@ namespace CXX else { os << "// " << ename (a) << endl - << "// " << endl; + << "//" << endl; } // Typedefs. @@ -2060,6 +2084,23 @@ namespace CXX os << endl; } + // Wildcard id. + // + if (ordered_p (c)) + { + if (doxygen) + os << "/**" << endl + << " * @brief Wildcard id used for capturing content " << + "order." << endl + << " */" << endl; + + SemanticGraph::Context& ctx (a.context ()); + + os << "static const ::std::size_t " << + ctx.get ("ordered-id-name") << " = " << + ctx.get ("ordered-id") << "UL;" << endl; + } + any_function_.traverse (a); if (doxygen) @@ -2095,7 +2136,7 @@ namespace CXX else { os << "// " << ename (a) << endl - << "// " << endl; + << "//" << endl; } if (doxygen) @@ -2288,6 +2329,8 @@ namespace CXX if (renamed_type (c, name) && !name) return; + SemanticGraph::Context& ctx (c.context ()); + bool has_members (has (c)); bool hae (has (c)); @@ -2295,6 +2338,9 @@ namespace CXX bool gen_wildcard (options.generate_wildcard ()); + bool mixed (mixed_p (c) && !ctx.count ("mixed-in-base")); + bool ordered (ordered_p (c) && !ctx.count ("order-in-base")); + bool simple (true); { IsSimpleType t (simple); @@ -2344,18 +2390,149 @@ namespace CXX // names (c, names_); - // dom_document accessors. + // Mixed content. // - if (edom_document_member_p (c)) + if (mixed) { + String const& type (ctx.get ("mixed-type")); + String const& cont (ctx.get ("mixed-container")); + String const& iter (ctx.get ("mixed-iterator")); + String const& citer (ctx.get ("mixed-const-iterator")); - if (!doxygen) - { - os << "// DOMDocument for wildcard content." << endl + if (doxygen) + os << "/**" << endl + << " * @name " << comment ("text_content") << endl + << " *" << endl + << " * @brief Accessor and modifier functions for text " << + "content." << endl + << " */" << endl + << "//@{" << endl; + else + os << "// text_content" << endl << "//" << endl; - } + + // Typedefs. + // + bool isense (options.generate_intellisense ()); + + if (doxygen) + os << endl + << "/**" << endl + << " * @brief Text content type." << endl + << " */" << endl; + + os << "typedef " << xs_string_type << " " << type << ";"; + + if (doxygen) + os << endl + << "/**" << endl + << " * @brief Text content sequence container type." << endl + << " */" << endl; + + os << "typedef ::xsd::cxx::tree::sequence< " << type << + " > " << cont << ";"; + + + if (doxygen) + os << endl + << "/**" << endl + << " * @brief Text content iterator type." << endl + << " */" << endl; + + // IntelliSense does not like aliases and fully-qualified + // names here. + // + if (!isense) + os << "typedef " << cont << "::iterator " << iter<< ";"; + else + os << "typedef ::xsd::cxx::tree::sequence< " << type << + " >::iterator " << iter << ";"; + + if (doxygen) + os << endl + << "/**" << endl + << " * @brief Text content constant iterator type." << endl + << " */" << endl; + + if (!isense) + os << "typedef " << cont << "::const_iterator " << citer<< ";"; + else + os << "typedef ::xsd::cxx::tree::sequence< " << type << + " >::const_iterator " << citer << ";"; + + os << endl; + + // Content id. + // + if (doxygen) + os << "/**" << endl + << " * @brief Text content id used for capturing content " << + "order." << endl + << " */" << endl; + + os << "static const ::std::size_t " << + ctx.get ("mixed-ordered-id-name") << " = " << + ctx.get ("mixed-ordered-id") << "UL;" << endl; + + // Accessors and modifiers. + // + String const& aname (ctx.get ("mixed-aname")); + String const& mname (ctx.get ("mixed-mname")); + + if (doxygen) + os << "/**" << endl + << " * @brief Return a read-only (constant) reference " << + "to the text" << endl + << " * content sequence." << endl + << " *" << endl + << " * @return A constant reference to the sequence " << + "container." << endl + << " */" << endl; + + os << "const " << cont << "&" << endl + << aname << " () const;" + << endl; + + if (doxygen) + os << "/**" << endl + << " * @brief Return a read-write reference to the " << + "text content" << endl + << " * sequence." << endl + << " *" << endl + << " * @return A reference to the sequence container." << endl + << " */" << endl; + + os << cont << "&" << endl + << aname << " ();" + << endl; + + if (doxygen) + os << "/**" << endl + << " * @brief Copy elements from a given sequence." << endl + << " *" << endl + << " * @param s A sequence to copy entries from." << endl + << " *" << endl + << " * For each element in @a s this function " << + "add it to the sequence." << endl + << " * Note that this operation " << + "completely changes the sequence and" << endl + << " * all old elements will be lost." << endl + << " */" << endl; + + os << "void" << endl + << mname << " (const " << cont << "& s);" + << endl; if (doxygen) + os << "//@}" << endl + << endl; + } + + // dom_document accessors. + // + if (edom_document_member_p (c)) + { + if (doxygen) { os << "/**" << endl << " * @brief Return a read-only (constant) reference " << @@ -2369,6 +2546,9 @@ namespace CXX << " * the raw XML content corresponding to wildcards." << endl << " */" << endl; } + else + os << "// DOMDocument for wildcard content." << endl + << "//" << endl; os << "const " << xerces_ns << "::DOMDocument&" << endl << edom_document (c) << " () const;" @@ -2393,6 +2573,137 @@ namespace CXX << endl; } + // Order container. + // + if (ordered) + { + String const& type (ctx.get ("order-type")); + String const& cont (ctx.get ("order-container")); + String const& iter (ctx.get ("order-iterator")); + String const& citer (ctx.get ("order-const-iterator")); + + String const ct (options.order_container_specified () + ? options.order_container () + : "::std::vector"); + + if (doxygen) + os << "/**" << endl + << " * @name " << comment ("content_order") << endl + << " *" << endl + << " * @brief Accessor and modifier functions for content " << + "order." << endl + << " */" << endl + << "//@{" << endl; + else + os << "// content_order" << endl + << "//" << endl; + + // Typedefs. + // + bool isense (options.generate_intellisense ()); + + if (doxygen) + os << endl + << "/**" << endl + << " * @brief Content order entry type." << endl + << " */" << endl; + + os << "typedef " << ns_name (xs_ns ()) << "::" << + xs_ns ().context ().get ("content-order") << " " << + type << ";"; + + if (doxygen) + os << endl + << "/**" << endl + << " * @brief Content order sequence container type." << endl + << " */" << endl; + + os << "typedef " << ct << "< " << type << " > " << cont << ";"; + + + if (doxygen) + os << endl + << "/**" << endl + << " * @brief Content order iterator type." << endl + << " */" << endl; + + // IntelliSense does not like aliases and fully-qualified + // names here. + // + if (!isense) + os << "typedef " << cont << "::iterator " << iter<< ";"; + else + os << "typedef " << ct << "< " << type << " >::iterator " << + iter << ";"; + + if (doxygen) + os << endl + << "/**" << endl + << " * @brief Content order constant iterator type." << endl + << " */" << endl; + + if (!isense) + os << "typedef " << cont << "::const_iterator " << citer<< ";"; + else + os << "typedef " << ct << "< " << type << + " >::const_iterator " << citer << ";"; + + os << endl; + + // Accessors and modifiers. + // + String const& aname (ctx.get ("order-aname")); + String const& mname (ctx.get ("order-mname")); + + if (doxygen) + os << "/**" << endl + << " * @brief Return a read-only (constant) reference " << + "to the content" << endl + << " * order sequence." << endl + << " *" << endl + << " * @return A constant reference to the sequence " << + "container." << endl + << " */" << endl; + + os << "const " << cont << "&" << endl + << aname << " () const;" + << endl; + + if (doxygen) + os << "/**" << endl + << " * @brief Return a read-write reference to the " << + "content order" << endl + << " * sequence." << endl + << " *" << endl + << " * @return A reference to the sequence container." << endl + << " */" << endl; + + os << cont << "&" << endl + << aname << " ();" + << endl; + + if (doxygen) + os << "/**" << endl + << " * @brief Copy elements from a given sequence." << endl + << " *" << endl + << " * @param s A sequence to copy entries from." << endl + << " *" << endl + << " * For each element in @a s this function " << + "add it to the sequence." << endl + << " * Note that this operation " << + "completely changes the sequence and" << endl + << " * all old elements will be lost." << endl + << " */" << endl; + + os << "void" << endl + << mname << " (const " << cont << "& s);" + << endl; + + if (doxygen) + os << "//@}" << endl + << endl; + } + if (doxygen) { os << "/**" << endl @@ -3042,7 +3353,7 @@ namespace CXX // Data members and implementation functions. // - if (has_members || hae || (haa && gen_wildcard)) + if (has_members || hae || (haa && gen_wildcard) || ordered || mixed) { os << "// Implementation." << endl << "//" << endl; @@ -3052,9 +3363,10 @@ namespace CXX << "//@cond" << endl << endl; - if (!options.suppress_parsing ()) + if (!options.suppress_parsing () && + (has_members || hae || (haa && gen_wildcard) || mixed)) { - // parse (xercesc::DOMElement) + // parse () // os << "protected:" << endl << "void" << endl @@ -3082,7 +3394,7 @@ namespace CXX } } - // + // DOM document. // if (edom_document_member_p (c)) { @@ -3091,6 +3403,24 @@ namespace CXX << endl; } + // Mixed text content. + // + if (mixed) + { + os << ctx.get ("mixed-container") << " " << + ctx.get ("mixed-member") << ";" + << endl; + } + + // Order container. + // + if (ordered) + { + os << ctx.get ("order-container") << " " << + ctx.get ("order-member") << ";" + << endl; + } + // // names (c, names_data_); @@ -3811,6 +4141,15 @@ namespace CXX if (ctx.std >= cxx_version::cxx11) ctx.os << "#include // std::move" << endl; + if (!ctx.options.ordered_type ().empty () || + ctx.options.ordered_type_all ()) + { + ctx.os << "#include // std::size_t" << endl; + + if (!ctx.options.order_container_specified ()) + ctx.os << "#include " << endl; + } + ctx.os << endl; if (ctx.char_type == L"char" && ctx.char_encoding != L"custom") diff --git a/xsd/cxx/tree/tree-inline.cxx b/xsd/cxx/tree/tree-inline.cxx index 1c01e5a..e6ed756 100644 --- a/xsd/cxx/tree/tree-inline.cxx +++ b/xsd/cxx/tree/tree-inline.cxx @@ -891,6 +891,41 @@ namespace CXX Complex::names (c, names); + // Mixed text content. + // + if (mixed_p (c) && !c.context ().count ("mixed-in-base")) + { + SemanticGraph::Context& ctx (c.context ()); + + String const& cont (ctx.get ("mixed-container")); + String const& memb (ctx.get ("mixed-member")); + + String const& aname (ctx.get ("mixed-aname")); + String const& mname (ctx.get ("mixed-mname")); + + os << inl + << "const " << name << "::" << cont << "& " << + name << "::" << endl + << aname << " () const" + << "{" + << "return this->" << memb << ";" + << "}"; + + os << inl + << name << "::" << cont << "& " << name << "::" << endl + << aname << " ()" + << "{" + << "return this->" << memb << ";" + << "}"; + + os << inl + << "void " << name << "::" << endl + << mname << " (const " << cont << "& s)" + << "{" + << "this->" << memb << " = s;" + << "}"; + } + // dom_document accessors. // if (edom_document_member_p (c)) @@ -900,14 +935,49 @@ namespace CXX name << "::" << endl << edom_document (c) << " () const" << "{" - << "return *" << edom_document_member (c) << ";" + << "return *this->" << edom_document_member (c) << ";" << "}"; os << inl << xerces_ns << "::DOMDocument& " << name << "::" << endl << edom_document (c) << " ()" << "{" - << "return *" << edom_document_member (c) << ";" + << "return *this->" << edom_document_member (c) << ";" + << "}"; + } + + // Order container. + // + if (ordered_p (c) && !c.context ().count ("order-in-base")) + { + SemanticGraph::Context& ctx (c.context ()); + + String const& cont (ctx.get ("order-container")); + String const& memb (ctx.get ("order-member")); + + String const& aname (ctx.get ("order-aname")); + String const& mname (ctx.get ("order-mname")); + + os << inl + << "const " << name << "::" << cont << "& " << + name << "::" << endl + << aname << " () const" + << "{" + << "return this->" << memb << ";" + << "}"; + + os << inl + << name << "::" << cont << "& " << name << "::" << endl + << aname << " ()" + << "{" + << "return this->" << memb << ";" + << "}"; + + os << inl + << "void " << name << "::" << endl + << mname << " (const " << cont << "& s)" + << "{" + << "this->" << memb << " = s;" << "}"; } diff --git a/xsd/cxx/tree/tree-source.cxx b/xsd/cxx/tree/tree-source.cxx index 036f7ae..110cb25 100644 --- a/xsd/cxx/tree/tree-source.cxx +++ b/xsd/cxx/tree/tree-source.cxx @@ -693,6 +693,9 @@ namespace CXX if (skip (e)) return; + SemanticGraph::Complex& c ( + dynamic_cast (e.scope ())); + String const& member (emember (e)); String tr (etraits (e)); // traits type name @@ -849,6 +852,27 @@ namespace CXX } } + // 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. @@ -920,10 +944,11 @@ namespace CXX { 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 ( - dynamic_cast (a.scope ()))); + String const& dom_doc (edom_document (c)); os << "// " << ename (a) << endl << "//" << endl @@ -1004,7 +1029,7 @@ namespace CXX { // sequence // - os << "this->" << member << " .push_back (r);"; + os << "this->" << member << ".push_back (r);"; } else if (min (a) == 0) { @@ -1019,6 +1044,31 @@ namespace CXX 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. @@ -2042,6 +2092,9 @@ namespace CXX 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_)) @@ -2232,6 +2285,11 @@ namespace CXX if (renamed_type (c, name) && !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); @@ -2348,6 +2406,12 @@ namespace CXX " > ())"; } + if (mixed) + { + os << "," << endl + << " " << ctx.get ("mixed-member") << " (this)"; + } + names (c, default_ctor_init_names_); os << "{"; @@ -2403,6 +2467,12 @@ namespace CXX " > ())"; } + if (mixed) + { + os << "," << endl + << " " << ctx.get ("mixed-member") << " (this)"; + } + names (c, ctor_names_); os << "{"; @@ -2437,6 +2507,12 @@ namespace CXX " > ())"; } + if (mixed) + { + os << "," << endl + << " " << ctx.get ("mixed-member") << " (this)"; + } + { CtorMember t (*this, at); Traversal::Names n (t); @@ -2481,6 +2557,12 @@ namespace CXX " > ())"; } + if (mixed) + { + os << "," << endl + << " " << ctx.get ("mixed-member") << " (this)"; + } + { CtorMember t (*this, at); Traversal::Names n (t); @@ -2529,6 +2611,12 @@ namespace CXX " > ())"; } + if (mixed) + { + os << "," << endl + << " " << ctx.get ("mixed-member") << " (this)"; + } + names (c, ctor_names_); os << "{"; @@ -2568,6 +2656,12 @@ namespace CXX " > ())"; } + if (mixed) + { + os << "," << endl + << " " << ctx.get ("mixed-member") << " (this)"; + } + { CtorMember t (*this, at); Traversal::Names n (t); @@ -2616,6 +2710,12 @@ namespace CXX " > ())"; } + if (mixed) + { + os << "," << endl + << " " << ctx.get ("mixed-member") << " (this)"; + } + { CtorMember t (*this, at); Traversal::Names n (t); @@ -2673,6 +2773,8 @@ namespace CXX " > ())"; } + // Cannot be mixed. + names (c, ctor_names_); os << "{"; @@ -2714,6 +2816,8 @@ namespace CXX " > ())"; } + // Cannot be mixed. + names (c, ctor_names_); os << "{"; @@ -2752,6 +2856,8 @@ namespace CXX " > ())"; } + // Cannot be mixed. + names (c, ctor_names_); os << "{"; @@ -2795,6 +2901,12 @@ namespace CXX " > ())"; } + if (mixed) + { + os << "," << endl + << " " << ctx.get ("mixed-member") << " (this)"; + } + names (c, ctor_names_); os << "{"; @@ -2839,6 +2951,12 @@ namespace CXX " > ())"; } + if (mixed) + { + os << "," << endl + << " " << ctx.get ("mixed-member") << " (this)"; + } + { CtorMember t (*this, at); Traversal::Names n (t); @@ -2892,6 +3010,12 @@ namespace CXX " > ())"; } + if (mixed) + { + os << "," << endl + << " " << ctx.get ("mixed-member") << " (this)"; + } + { CtorMember t (*this, at); Traversal::Names n (t); @@ -2926,6 +3050,20 @@ namespace CXX " > ())"; } + 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"); @@ -2964,7 +3102,7 @@ namespace CXX << container << "* c)" << endl << ": " << base << " (e, f"; - if (he || ha || hae || (haa && gen_wildcard)) + if (he || ha || hae || (haa && gen_wildcard) || mixed) os << " | " << flags_type << "::base"; os << ", c)"; @@ -2977,6 +3115,12 @@ namespace CXX " > ())"; } + if (mixed) + { + os << "," << endl + << " " << ctx.get ("mixed-member") << " (this)"; + } + names (c, element_ctor_names_); os << "{"; @@ -2988,9 +3132,9 @@ namespace CXX bool base_has_el (false), base_has_at (false); // We are only interested in this information if we are - // generating out own parse(). + // generating our own parse(). // - if (he || ha || hae || (haa && gen_wildcard)) + if (he || ha || hae || (haa && gen_wildcard) || mixed) { if (c.inherits_p ()) { @@ -2999,13 +3143,14 @@ namespace CXX } } - //@@ throw if p is no exhausted at the end. + //@@ Throw if p is not exhausted at the end. // - if (he || ha || hae || (haa && gen_wildcard)) + if (he || ha || hae || (haa && gen_wildcard) || mixed) os << "if ((f & " << flags_type << "::base) == 0)" << "{" << parser_type << " p (e, " << - (he || hae || base_has_el ? "true, " : "false, ") << + (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);" @@ -3051,7 +3196,7 @@ namespace CXX os << "}"; } - if (he || ha || hae || (haa && gen_wildcard)) + if (he || ha || hae || (haa && gen_wildcard) || mixed) { os << "void " << name << "::" << endl << unclash (name, "parse") << " (" << @@ -3066,17 +3211,45 @@ namespace CXX os << "this->" << base << "::parse (p, f);" << endl; - if (he || hae) + if (he || hae || mixed_p (c)) { - os << "for (; p.more_elements (); p.next_element ())" - << "{" - << "const " << xerces_ns << "::DOMElement& i (" << - "p.cur_element ());" - << "const " << qname_type << " n (" << endl - << "::xsd::cxx::xml::dom::name< " << char_type << " > (i));" - << endl; + bool m (mixed_p (c)); + + os << "for (; p.more_content (); p.next_content (" << + (m ? "true" : "false") << "))" + << "{"; - names (c, names_element_); + 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;" << "}"; @@ -3152,7 +3325,23 @@ namespace CXX // 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 << "}" @@ -3203,7 +3392,7 @@ namespace CXX // Comparison operators. // if (options.generate_comparison () && - (he || ha || !c.inherits_p () || + (he || ha || mixed || ordered || !c.inherits_p () || ((hae || haa) && gen_wildcard))) { bool base_comp (false); @@ -3214,8 +3403,8 @@ namespace CXX test.dispatch (c.inherits ().base ()); } - bool has_body (he || ha || base_comp || - ((hae || haa) && gen_wildcard)); + bool has_body (he || ha || ordered || mixed || base_comp || + ((hae || haa) && gen_wildcard)); os << "bool" << endl << "operator== (const " << name << "&" << @@ -3233,6 +3422,22 @@ namespace CXX 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;" << "}"; diff --git a/xsd/makefile b/xsd/makefile index 06ea02c..d57022d 100644 --- a/xsd/makefile +++ b/xsd/makefile @@ -31,6 +31,7 @@ cxx_tun += cxx/tree/elements.cxx \ cxx/tree/validator.cxx \ cxx/tree/counter.cxx \ cxx/tree/name-processor.cxx \ + cxx/tree/order-processor.cxx \ cxx/tree/polymorphism-processor.cxx \ cxx/tree/default-value.cxx \ cxx/tree/generator.cxx \ @@ -114,6 +115,7 @@ endif $(gen): cli := $(cli) $(gen): cli_options += \ -I $(src_base) \ +--generate-specifier \ --ostream-type ::std::wostream \ --exclude-base \ --suppress-undocumented \ diff --git a/xsd/options-parser.hxx b/xsd/options-parser.hxx index 10456e1..0f370cd 100644 --- a/xsd/options-parser.hxx +++ b/xsd/options-parser.hxx @@ -14,8 +14,9 @@ namespace cli struct parser { static void - parse (NarrowString& x, scanner& s) + parse (NarrowString& x, bool& xs, scanner& s) { + xs = true; const char* o (s.next ()); if (s.more ()) -- cgit v1.1