aboutsummaryrefslogtreecommitdiff
path: root/xsd
diff options
context:
space:
mode:
authorBoris Kolpackov <boris@codesynthesis.com>2014-04-10 12:57:06 +0200
committerBoris Kolpackov <boris@codesynthesis.com>2014-04-10 12:57:06 +0200
commit884dea7531962b17ef843ac2175faa050e8b0758 (patch)
treed70950ab2a6f314b06f37faa67252678ce3007b1 /xsd
parent0f6ff689dc6bae8fed94da0fcabd39f015e7a62b (diff)
Add support for ordered types, mixed content
Diffstat (limited to 'xsd')
-rw-r--r--xsd/cxx/tree/elements.hxx71
-rw-r--r--xsd/cxx/tree/fundamental-header.hxx11
-rw-r--r--xsd/cxx/tree/generator.cxx10
-rw-r--r--xsd/cxx/tree/name-processor.cxx285
-rw-r--r--xsd/cxx/tree/options.cli60
-rw-r--r--xsd/cxx/tree/order-processor.cxx244
-rw-r--r--xsd/cxx/tree/order-processor.hxx30
-rw-r--r--xsd/cxx/tree/polymorphism-processor.cxx64
-rw-r--r--xsd/cxx/tree/serialization-source.cxx219
-rw-r--r--xsd/cxx/tree/tree-header.cxx369
-rw-r--r--xsd/cxx/tree/tree-inline.cxx74
-rw-r--r--xsd/cxx/tree/tree-source.cxx251
-rw-r--r--xsd/makefile2
-rw-r--r--xsd/options-parser.hxx3
14 files changed, 1550 insertions, 143 deletions
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 <map>
+#include <set>
#include <deque>
#include <vector>
#include <sstream>
@@ -68,6 +69,54 @@ namespace CXX
String reason_;
};
+ // A set of potentially qualified XML Schema type names.
+ //
+ struct TypeNameSet
+ {
+ template <typename I>
+ 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<String> 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<bool> ("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<String> ("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 <cxx/tree/counter.hxx>
#include <cxx/tree/validator.hxx>
#include <cxx/tree/name-processor.hxx>
+#include <cxx/tree/order-processor.hxx>
#include <cxx/tree/polymorphism-processor.hxx>
#include <cxx/tree/tree-forward.hxx>
@@ -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<SemanticGraph::Complex&> (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<String> ("name"));
bool def_attr (m.default_p () &&
- m.is_a<SemanticGraph::Attribute> ());
+ m.is_a<SemanticGraph::Attribute> ());
// 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<SemanticGraph::Element> () && 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<SemanticGraph::Complex&> (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<String> ("name"));
+ String name (ctx.get<String> ("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<NameSet> ("cxx-tree-name-processor-stem-set"));
+ ctx.get<NameSet> ("cxx-tree-name-processor-stem-set"));
NameSet& member_set (
- cc.get<NameSet> ("cxx-tree-name-processor-member-set"));
+ ctx.get<NameSet> ("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<Complex*> (
+ &p->inherits ().base ()))
+ {
+ if (mixed_p (*b))
+ {
+ SemanticGraph::Context& bctx (b->context ());
+ ctx.set ("mixed-type", bctx.get<String> ("mixed-type"));
+ ctx.set ("mixed-const-iterator",
+ bctx.get<String> ("mixed-const-iterator"));
+ ctx.set ("mixed-ordered-id-name",
+ bctx.get<String> ("mixed-ordered-id-name"));
+ ctx.set ("mixed-aname", bctx.get<String> ("mixed-aname"));
+ ctx.set ("mixed-member", bctx.get<String> ("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<Complex*> (
+ &p->inherits ().base ()))
+ {
+ if (ordered_p (*b))
+ {
+ SemanticGraph::Context& bctx (b->context ());
+ ctx.set ("order-type", bctx.get<String> ("order-type"));
+ ctx.set ("order-const-iterator",
+ bctx.get<String> ("order-const-iterator"));
+ ctx.set ("order-aname", bctx.get<String> ("order-aname"));
+ ctx.set ("order-member", bctx.get<String> ("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
+ {
+ "<type>",
+ "Indicate that element order in <type> 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 <type> 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
+ {
+ "<type>",
+ "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
+ {
+ "<regex>",
+ "Add <regex> 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
{
"<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 <iostream>
+
+#include <cxx/tree/elements.hxx>
+#include <cxx/tree/order-processor.hxx>
+
+#include <xsd-frontend/semantic-graph.hxx>
+#include <xsd-frontend/traversal.hxx>
+
+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<Complex*> (&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<size_t> ("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 <xsd-frontend/semantic-graph.hxx>
+
+#include <xsd.hxx>
+#include <types.hxx>
+
+#include <cxx/tree/options.hxx>
+
+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 <set>
#include <iostream>
#include <cxx/tree/elements.hxx>
@@ -19,59 +18,12 @@ namespace CXX
{
namespace
{
- struct TypeSet
- {
- template <typename I>
- 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<String> 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<SemanticGraph::Complex&> (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<String> ("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<size_t> ("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<SemanticGraph::Complex&> (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<String> ("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<size_t> ("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<size_t> ("ordered-start");
+ count = ctx.get<size_t> ("ordered-count");
+
+ if (start != count)
+ {
+ String const& ci (ctx.get<String> ("order-const-iterator"));
+ String const& an (ctx.get<String> ("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<String> ("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<String> ("mixed-aname") <<
+ " ()[b->index].c_str ()).c_str ()));";
+
+ // os << "e << i." << ctx.get<String> ("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<SemanticGraph::Attribute> ());
+ m.is_a<SemanticGraph::Attribute> ());
if (max (m) != 1)
{
@@ -1784,6 +1784,9 @@ namespace CXX
if (skip (m))
return;
+ SemanticGraph::Complex& c (
+ dynamic_cast<SemanticGraph::Complex&> (m.scope ()));
+
String const& type (etype (m));
bool el (m.is_a<SemanticGraph::Element> ());
@@ -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<String> ("ordered-id-name") << " = " <<
+ ctx.get<size_t> ("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<SemanticGraph::Complex&> (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<String> ("ordered-id-name") << " = " <<
+ ctx.get<size_t> ("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<Traversal::Member> (c));
bool hae (has<Traversal::Any> (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<String> ("mixed-type"));
+ String const& cont (ctx.get<String> ("mixed-container"));
+ String const& iter (ctx.get<String> ("mixed-iterator"));
+ String const& citer (ctx.get<String> ("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<String> ("mixed-ordered-id-name") << " = " <<
+ ctx.get<size_t> ("mixed-ordered-id") << "UL;" << endl;
+
+ // Accessors and modifiers.
+ //
+ String const& aname (ctx.get<String> ("mixed-aname"));
+ String const& mname (ctx.get<String> ("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<String> ("order-type"));
+ String const& cont (ctx.get<String> ("order-container"));
+ String const& iter (ctx.get<String> ("order-iterator"));
+ String const& citer (ctx.get<String> ("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<String> ("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<String> ("order-aname"));
+ String const& mname (ctx.get<String> ("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<String> ("mixed-container") << " " <<
+ ctx.get<String> ("mixed-member") << ";"
+ << endl;
+ }
+
+ // Order container.
+ //
+ if (ordered)
+ {
+ os << ctx.get<String> ("order-container") << " " <<
+ ctx.get<String> ("order-member") << ";"
+ << endl;
+ }
+
//
//
names (c, names_data_);
@@ -3811,6 +4141,15 @@ namespace CXX
if (ctx.std >= cxx_version::cxx11)
ctx.os << "#include <utility> // std::move" << endl;
+ if (!ctx.options.ordered_type ().empty () ||
+ ctx.options.ordered_type_all ())
+ {
+ ctx.os << "#include <cstddef> // std::size_t" << endl;
+
+ if (!ctx.options.order_container_specified ())
+ ctx.os << "#include <vector>" << 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<String> ("mixed-container"));
+ String const& memb (ctx.get<String> ("mixed-member"));
+
+ String const& aname (ctx.get<String> ("mixed-aname"));
+ String const& mname (ctx.get<String> ("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<String> ("order-container"));
+ String const& memb (ctx.get<String> ("order-member"));
+
+ String const& aname (ctx.get<String> ("order-aname"));
+ String const& mname (ctx.get<String> ("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<SemanticGraph::Complex&> (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<String> ("order-type"));
+ String const& m (ctx.get<String> ("order-member"));
+
+ os << "this->" << m << ".push_back (" << endl
+ << t << " (" <<
+ e.context ().get<String> ("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<SemanticGraph::Complex&> (a.scope ()));
+
String const& ns (a.definition_namespace ().name ());
- String const& dom_doc (
- edom_document (
- dynamic_cast<SemanticGraph::Complex&> (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<String> ("order-type"));
+ String const& m (ctx.get<String> ("order-member"));
+
+ os << "this->" << m << ".push_back (" << endl
+ << t << " (" <<
+ a.context ().get<String> ("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<String> ("mixed-member") << " (this)";
+ }
+
names (c, default_ctor_init_names_);
os << "{";
@@ -2403,6 +2467,12 @@ namespace CXX
" > ())";
}
+ if (mixed)
+ {
+ os << "," << endl
+ << " " << ctx.get<String> ("mixed-member") << " (this)";
+ }
+
names (c, ctor_names_);
os << "{";
@@ -2437,6 +2507,12 @@ namespace CXX
" > ())";
}
+ if (mixed)
+ {
+ os << "," << endl
+ << " " << ctx.get<String> ("mixed-member") << " (this)";
+ }
+
{
CtorMember t (*this, at);
Traversal::Names n (t);
@@ -2481,6 +2557,12 @@ namespace CXX
" > ())";
}
+ if (mixed)
+ {
+ os << "," << endl
+ << " " << ctx.get<String> ("mixed-member") << " (this)";
+ }
+
{
CtorMember t (*this, at);
Traversal::Names n (t);
@@ -2529,6 +2611,12 @@ namespace CXX
" > ())";
}
+ if (mixed)
+ {
+ os << "," << endl
+ << " " << ctx.get<String> ("mixed-member") << " (this)";
+ }
+
names (c, ctor_names_);
os << "{";
@@ -2568,6 +2656,12 @@ namespace CXX
" > ())";
}
+ if (mixed)
+ {
+ os << "," << endl
+ << " " << ctx.get<String> ("mixed-member") << " (this)";
+ }
+
{
CtorMember t (*this, at);
Traversal::Names n (t);
@@ -2616,6 +2710,12 @@ namespace CXX
" > ())";
}
+ if (mixed)
+ {
+ os << "," << endl
+ << " " << ctx.get<String> ("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<String> ("mixed-member") << " (this)";
+ }
+
names (c, ctor_names_);
os << "{";
@@ -2839,6 +2951,12 @@ namespace CXX
" > ())";
}
+ if (mixed)
+ {
+ os << "," << endl
+ << " " << ctx.get<String> ("mixed-member") << " (this)";
+ }
+
{
CtorMember t (*this, at);
Traversal::Names n (t);
@@ -2892,6 +3010,12 @@ namespace CXX
" > ())";
}
+ if (mixed)
+ {
+ os << "," << endl
+ << " " << ctx.get<String> ("mixed-member") << " (this)";
+ }
+
{
CtorMember t (*this, at);
Traversal::Names n (t);
@@ -2926,6 +3050,20 @@ namespace CXX
" > ())";
}
+ if (mixed)
+ {
+ String const& m (ctx.get<String> ("mixed-member"));
+ os << "," << endl
+ << " " << m << " (x." << m << ", f, this)";
+ }
+
+ if (ordered)
+ {
+ String const& m (ctx.get<String> ("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<String> ("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<String> ("mixed-aname"));
+ String const& mi (ctx.get<String> ("mixed-ordered-id-name"));
+ String const& oa (ctx.get<String> ("order-aname"));
+ String const& ot (ctx.get<String> ("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<String> ("mixed-member"));
+ os << "this->" << m << " = x." << m << ";";
+ }
+
+ // Order container.
+ //
+ if (ordered)
+ {
+ String const& m (ctx.get<String> ("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<String> ("mixed-aname"));
+ os << "if (!(x." << an << " () == y." << an << " ()))" << endl
+ << "return false;"
+ << endl;
+ }
+
+ if (ordered)
+ {
+ String const& an (ctx.get<String> ("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<NarrowString>
{
static void
- parse (NarrowString& x, scanner& s)
+ parse (NarrowString& x, bool& xs, scanner& s)
{
+ xs = true;
const char* o (s.next ());
if (s.more ())