aboutsummaryrefslogtreecommitdiff
path: root/xsde/cxx/serializer
diff options
context:
space:
mode:
authorBoris Kolpackov <boris@codesynthesis.com>2009-02-24 15:16:26 +0200
committerBoris Kolpackov <boris@codesynthesis.com>2009-02-24 15:16:26 +0200
commit707cc94fe52463870a9c6c8e2e66eaaa389e601d (patch)
tree13e10ff28bf4455d915f9d59b401bdbb62a393cb /xsde/cxx/serializer
Start tracking XSD/e with git after version 3.0.03.0.0
Diffstat (limited to 'xsde/cxx/serializer')
-rw-r--r--xsde/cxx/serializer/attribute-validation-source.cxx463
-rw-r--r--xsde/cxx/serializer/attribute-validation-source.hxx22
-rw-r--r--xsde/cxx/serializer/cli.hxx154
-rw-r--r--xsde/cxx/serializer/driver-source.cxx1047
-rw-r--r--xsde/cxx/serializer/driver-source.hxx22
-rw-r--r--xsde/cxx/serializer/element-validation-source.cxx903
-rw-r--r--xsde/cxx/serializer/element-validation-source.hxx22
-rw-r--r--xsde/cxx/serializer/elements.cxx278
-rw-r--r--xsde/cxx/serializer/elements.hxx443
-rw-r--r--xsde/cxx/serializer/generator.cxx1600
-rw-r--r--xsde/cxx/serializer/generator.hxx56
-rw-r--r--xsde/cxx/serializer/impl-header.cxx488
-rw-r--r--xsde/cxx/serializer/impl-header.hxx22
-rw-r--r--xsde/cxx/serializer/impl-source.cxx664
-rw-r--r--xsde/cxx/serializer/impl-source.hxx22
-rw-r--r--xsde/cxx/serializer/name-processor.cxx1409
-rw-r--r--xsde/cxx/serializer/name-processor.hxx32
-rw-r--r--xsde/cxx/serializer/serializer-forward.cxx112
-rw-r--r--xsde/cxx/serializer/serializer-forward.hxx22
-rw-r--r--xsde/cxx/serializer/serializer-header.cxx2006
-rw-r--r--xsde/cxx/serializer/serializer-header.hxx22
-rw-r--r--xsde/cxx/serializer/serializer-inline.cxx631
-rw-r--r--xsde/cxx/serializer/serializer-inline.hxx22
-rw-r--r--xsde/cxx/serializer/serializer-source.cxx2703
-rw-r--r--xsde/cxx/serializer/serializer-source.hxx22
-rw-r--r--xsde/cxx/serializer/type-processor.cxx356
-rw-r--r--xsde/cxx/serializer/type-processor.hxx34
-rw-r--r--xsde/cxx/serializer/validator.cxx501
-rw-r--r--xsde/cxx/serializer/validator.hxx36
29 files changed, 14114 insertions, 0 deletions
diff --git a/xsde/cxx/serializer/attribute-validation-source.cxx b/xsde/cxx/serializer/attribute-validation-source.cxx
new file mode 100644
index 0000000..59d3cb5
--- /dev/null
+++ b/xsde/cxx/serializer/attribute-validation-source.cxx
@@ -0,0 +1,463 @@
+// file : xsde/cxx/serializer/attribute-validation-source.cxx
+// author : Boris Kolpackov <boris@codesynthesis.com>
+// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC
+// license : GNU GPL v2 + exceptions; see accompanying LICENSE file
+
+#include <cxx/serializer/attribute-validation-source.hxx>
+
+#include <xsd-frontend/semantic-graph.hxx>
+#include <xsd-frontend/traversal.hxx>
+
+namespace CXX
+{
+ namespace Serializer
+ {
+ namespace
+ {
+ struct AnyAttributeTest: Traversal::AnyAttribute, Context
+ {
+ AnyAttributeTest (Context& c)
+ : Context (c)
+ {
+ }
+
+ virtual Void
+ traverse (SemanticGraph::AnyAttribute& a)
+ {
+ String const& ns (a.definition_namespace ().name ());
+
+ for (SemanticGraph::AnyAttribute::NamespaceIterator
+ i (a.namespace_begin ()), e (a.namespace_end ()); i != e;)
+ {
+ if (*i == L"##any")
+ {
+ if (stl)
+ os << "!name.empty ()";
+ else
+ os << "(name != 0 && *name != '\\0')";
+ }
+ else if (*i == L"##other")
+ {
+ if (ns)
+ {
+ // Note that here I assume that ##other does not include
+ // unqualified names in a schema with target namespace.
+ // This is not what the spec says but that seems to be
+ // the consensus.
+ //
+ if (stl)
+ os << "(!ns.empty () && ns != " << strlit (ns) << ")";
+ else
+ os << "(ns != 0 && *ns != '\\0' && " <<
+ "strcmp (ns, " << strlit (ns) << ") != 0)";
+ }
+ else
+ {
+ if (stl)
+ os << "!ns.empty ()";
+ else
+ os << "(ns != 0 && *ns != '\\0')";
+ }
+ }
+ else if (*i == L"##local")
+ {
+ if (stl)
+ os << "(ns.empty () && !name.empty ())";
+ else
+ os << "((ns == 0 || *ns == '\\0') && " <<
+ "name != 0 && *name != '\\0')";
+ }
+ else if (*i == L"##targetNamespace")
+ {
+ if (stl)
+ os << "ns == " << strlit (ns);
+ else
+ os << "(ns != 0 && strcmp (ns, " << strlit (ns) << ") == 0)";
+ }
+ else
+ {
+ if (stl)
+ os << "ns == " << strlit (*i);
+ else
+ os << "(ns != 0 && strcmp (ns, " << strlit (*i) << ") == 0)";
+ }
+
+ if (++i != e)
+ os << " ||" << endl;
+ }
+ }
+ };
+
+ struct Attribute: Traversal::Attribute,
+ Traversal::AnyAttribute,
+ Context
+ {
+ Attribute (Context& c)
+ : Context (c), any_attribute_test_ (c)
+ {
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Attribute& a)
+ {
+ String const& name (ename (a));
+
+ os << "// " << name << endl
+ << "//" << endl;
+
+ if (a.optional ())
+ {
+ os << "if (this->" << epresent (a) << " ())";
+ }
+
+ os << "{";
+
+ String const& inst (emember (a));
+ String const& ret (ret_type (a.type ()));
+ String const& arg (arg_type (a.type ()));
+
+ if (ret == L"void")
+ os << "this->" << name << " ();"
+ << endl;
+ else
+ os << arg << " r = this->" << name << " ();"
+ << endl;
+
+ if (!exceptions)
+ os << "if (ctx.error_type ())" << endl
+ << "return;"
+ << endl;
+
+ os << "if (this->" << inst << ")"
+ << "{";
+
+ if (ret == L"void")
+ os << "this->" << inst << "->pre ();";
+ else
+ os << "this->" << inst << "->pre (r);";
+
+ if (!exceptions)
+ os << endl
+ << "if (this->" << inst << "->_error_type ())" << endl
+ << "this->" << inst << "->_copy_error (ctx);"
+ << endl
+ << "if (ctx.error_type ())" << endl
+ << "return;"
+ << endl;
+
+ if (exceptions)
+ {
+ if (a.qualified () && a.namespace_ ().name ())
+ os << "this->_start_attribute (" <<
+ strlit (a.namespace_ ().name ()) << ", " <<
+ strlit (a.name ()) << ");";
+ else
+ os << "this->_start_attribute (" << strlit (a.name ()) << ");";
+ }
+ else
+ {
+ os << "if (!";
+
+ if (a.qualified () && a.namespace_ ().name ())
+ os << "this->_start_attribute (" <<
+ strlit (a.namespace_ ().name ()) << ", " <<
+ strlit (a.name ()) << ")";
+ else
+ os << "this->_start_attribute (" << strlit (a.name ()) << ")";
+
+ os << ")" << endl
+ << "return;"
+ << endl;
+ }
+
+ os << "this->" << inst << "->_pre_impl (ctx);";
+
+ os << endl
+ << "if (ctx.error_type ())" << endl
+ << "return;"
+ << endl;
+
+ os << "this->" << inst << "->_serialize_content ();";
+
+ os << endl
+ << "if (ctx.error_type ())" << endl
+ << "return;"
+ << endl;
+
+ os << "this->" << inst << "->_post_impl ();";
+
+ os << endl
+ << "if (ctx.error_type ())" << endl
+ << "return;"
+ << endl;
+
+ if (exceptions)
+ os << "this->_end_attribute ();";
+ else
+ os << "if (!this->_end_attribute ())" << endl
+ << "return;"
+ << endl;
+
+ os << "this->" << inst << "->post ();";
+
+ if (!exceptions)
+ os << endl
+ << "if (this->" << inst << "->_error_type ())" << endl
+ << "this->" << inst << "->_copy_error (ctx);"
+ << endl
+ << "if (ctx.error_type ())" << endl
+ << "return;";
+
+ os << "}"; // if (inst)
+
+ if (!a.optional ())
+ {
+ os << "else"
+ << "{"
+ << "this->_schema_error (" <<
+ "::xsde::cxx::schema_error::expected_attribute);"
+ << "return;"
+ << "}";
+ }
+
+ os << "}";
+
+ if (a.optional () && !exceptions)
+ {
+ os << "if (ctx.error_type ())" << endl
+ << "return;"
+ << endl;
+ }
+ }
+
+ virtual Void
+ traverse (SemanticGraph::AnyAttribute& a)
+ {
+ os << "while (this->" << enext (a) << " ())"
+ << "{";
+
+ if (stl)
+ {
+ os << "::std::string ns, name;"
+ << "this->" << ename (a) << " (ns, name);"
+ << endl;
+
+ if (!exceptions)
+ os << "if (ctx.error_type ())" << endl
+ << "return;"
+ << endl;
+
+ os << "if (";
+
+ any_attribute_test_.dispatch (a);
+
+ os << ")"
+ << "{";
+
+ os << "if (ns.empty ())"
+ << "{";
+
+ if (exceptions)
+ os << "this->_start_attribute (name.c_str ());";
+ else
+ os << "if (!this->_start_attribute (name.c_str ()))" << endl
+ << "return;";
+
+ os << "}"
+ << "else"
+ << "{";
+
+ if (exceptions)
+ os << "this->_start_attribute (ns.c_str (), name.c_str ());";
+ else
+ os << "if (!this->_start_attribute (ns.c_str (), " <<
+ "name.c_str ()))" << endl
+ << "return;";
+
+ os << "}"
+ << "this->" << eserialize (a) << " ();"
+ << endl
+ << "if (ctx.error_type ())" << endl
+ << "return;"
+ << endl;
+
+ if (exceptions)
+ os << "this->_end_attribute ();";
+ else
+ os << "if (!this->_end_attribute ())" << endl
+ << "return;";
+
+ os << "}" // test
+ << "else"
+ << "{"
+ << "this->_schema_error (" <<
+ "::xsde::cxx::schema_error::unexpected_attribute);"
+ << "return;"
+ << "}";
+ }
+ else
+ {
+ os << "const char* ns = 0;"
+ << "const char* name;"
+ << "bool free;"
+ << "this->" << ename (a) << " (ns, name, free);"
+ << endl;
+
+ if (!exceptions)
+ os << "if (ctx.error_type ())" << endl
+ << "return;"
+ << endl;
+ else
+ os << "::xsde::cxx::string auto_ns, auto_name;"
+ << "if (free)"
+ << "{"
+ << "auto_ns.attach (const_cast< char* > (ns));"
+ << "auto_name.attach (const_cast< char* > (name));"
+ << "}";
+
+ os << "if (";
+
+ any_attribute_test_.dispatch (a);
+
+ os << ")"
+ << "{";
+
+ if (exceptions)
+ os << "if (ns == 0 || *ns == '\\0')" << endl
+ << "this->_start_attribute (name);"
+ << "else" << endl
+ << "this->_start_attribute (ns, name);"
+ << endl;
+ else
+ os << "bool r;"
+ << "if (ns == 0 || *ns == '\\0')" << endl
+ << "r = this->_start_attribute (name);"
+ << "else" << endl
+ << "r = this->_start_attribute (ns, name);"
+ << endl
+ << "if (free)"
+ << "{"
+ << "delete[] ns;"
+ << "delete[] name;"
+ << "}"
+ << "if (!r)" << endl
+ << "return;"
+ << endl;
+
+ os << "this->" << eserialize (a) << " ();"
+ << endl
+ << "if (ctx.error_type ())" << endl
+ << "return;"
+ << endl;
+
+ if (exceptions)
+ os << "this->_end_attribute ();";
+ else
+ os << "if (!this->_end_attribute ())" << endl
+ << "return;";
+
+ os << "}" // test
+ << "else"
+ << "{"
+ << "this->_schema_error (" <<
+ "::xsde::cxx::schema_error::unexpected_attribute);"
+ << "return;"
+ << "}";
+ }
+
+ os << "}";
+
+ if (!exceptions)
+ os << "if (ctx.error_type ())" << endl
+ << "return;"
+ << endl;
+ }
+
+ private:
+ AnyAttributeTest any_attribute_test_;
+ };
+
+ struct Complex : Traversal::Complex, Context
+ {
+ Complex (Context& c)
+ : Context (c),
+ attribute_ (c)
+ {
+ names_attribute_ >> attribute_;
+ }
+
+ virtual Void
+ traverse (Type& c)
+ {
+ if (!has<Traversal::Attribute> (c) &&
+ !has<Traversal::AnyAttribute> (c))
+ return;
+
+ // Don't use restriction_p here since we don't want special
+ // treatment of anyType.
+ //
+ Boolean restriction (
+ c.inherits_p () &&
+ c.inherits ().is_a<SemanticGraph::Restricts> ());
+
+ String const& name (ename (c));
+
+ os <<"// Attribute validation and serialization for " <<
+ name << "." << endl
+ <<"//" << endl;
+
+ os << "void " << name << "::" << endl
+ << "_serialize_attributes ()"
+ << "{"
+ << "::xsde::cxx::serializer::context& ctx = this->_context ();"
+ << endl;
+
+ if (c.inherits_p () && !restriction)
+ {
+ // We cannot use the fully-qualified base name directly
+ // because of some broken compilers (EVC 4.0).
+ //
+ String base (unclash (name, "base"));
+
+ os << "typedef " << fq_name (c.inherits ().base ()) << " " <<
+ base << ";"
+ << base << "::_serialize_attributes ();"
+ << endl
+ << "if (ctx.error_type ())" << endl
+ << "return;"
+ << endl;
+ }
+
+ names (c, names_attribute_);
+
+ os << "}";
+ }
+
+ private:
+ Attribute attribute_;
+ Traversal::Names names_attribute_;
+ };
+ }
+
+ Void
+ generate_attribute_validation_source (Context& ctx)
+ {
+ Traversal::Schema schema;
+
+ Traversal::Sources sources;
+ Traversal::Names schema_names;
+
+ Namespace ns (ctx);
+ Traversal::Names names;
+
+ schema >> sources >> schema;
+ schema >> schema_names >> ns >> names;
+
+ Complex complex (ctx);
+
+ names >> complex;
+
+ schema.dispatch (ctx.schema_root);
+ }
+ }
+}
diff --git a/xsde/cxx/serializer/attribute-validation-source.hxx b/xsde/cxx/serializer/attribute-validation-source.hxx
new file mode 100644
index 0000000..d06890d
--- /dev/null
+++ b/xsde/cxx/serializer/attribute-validation-source.hxx
@@ -0,0 +1,22 @@
+// file : xsde/cxx/serializer/attribute-validation-source.hxx
+// author : Boris Kolpackov <boris@codesynthesis.com>
+// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC
+// license : GNU GPL v2 + exceptions; see accompanying LICENSE file
+
+#ifndef CXX_SERIALIZER_ATTRIBUTE_VALIDATION_SOURCE_HXX
+#define CXX_SERIALIZER_ATTRIBUTE_VALIDATION_SOURCE_HXX
+
+#include <xsd-frontend/semantic-graph/schema.hxx>
+
+#include <cxx/serializer/elements.hxx>
+
+namespace CXX
+{
+ namespace Serializer
+ {
+ Void
+ generate_attribute_validation_source (Context&);
+ }
+}
+
+#endif // CXX_SERIALIZER_ATTRIBUTE_VALIDATION_SOURCE_HXX
diff --git a/xsde/cxx/serializer/cli.hxx b/xsde/cxx/serializer/cli.hxx
new file mode 100644
index 0000000..5b1b7fa
--- /dev/null
+++ b/xsde/cxx/serializer/cli.hxx
@@ -0,0 +1,154 @@
+// file : xsde/cxx/serializer/cli.hxx
+// author : Boris Kolpackov <boris@codesynthesis.com>
+// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC
+// license : GNU GPL v2 + exceptions; see accompanying LICENSE file
+
+#ifndef CXX_SERIALIZER_CLI_HXX
+#define CXX_SERIALIZER_CLI_HXX
+
+#include <cult/types.hxx>
+
+#include <cult/containers/vector.hxx>
+
+#include <cult/cli/options.hxx>
+#include <cult/cli/options-spec.hxx>
+
+namespace CXX
+{
+ namespace Serializer
+ {
+ namespace CLI
+ {
+ using namespace Cult::Types;
+
+ typedef Char const Key[];
+
+ extern Key type_map;
+ extern Key no_stl;
+ extern Key no_iostream;
+ extern Key no_exceptions;
+ extern Key no_long_long;
+ extern Key reuse_style_mixin;
+ extern Key reuse_style_none;
+ extern Key generate_inline;
+ extern Key suppress_validation;
+ extern Key generate_polymorphic;
+ extern Key runtime_polymorphic;
+ extern Key suppress_reset;
+ extern Key generate_empty_impl;
+ extern Key generate_test_driver;
+ extern Key force_overwrite;
+ extern Key root_element_first;
+ extern Key root_element_last;
+ extern Key root_element;
+ extern Key generate_xml_schema;
+ extern Key extern_xml_schema;
+ extern Key output_dir;
+ extern Key skel_type_suffix;
+ extern Key skel_file_suffix;
+ extern Key impl_type_suffix;
+ extern Key impl_file_suffix;
+ extern Key namespace_map;
+ extern Key namespace_regex;
+ extern Key namespace_regex_trace;
+ extern Key reserved_name;
+ extern Key include_with_brackets;
+ extern Key include_prefix;
+ extern Key include_regex;
+ extern Key include_regex_trace;
+ extern Key guard_prefix;
+ extern Key hxx_suffix;
+ extern Key ixx_suffix;
+ extern Key cxx_suffix;
+ extern Key hxx_regex;
+ extern Key ixx_regex;
+ extern Key cxx_regex;
+ extern Key hxx_prologue;
+ extern Key ixx_prologue;
+ extern Key cxx_prologue;
+ extern Key prologue;
+ extern Key hxx_epilogue;
+ extern Key ixx_epilogue;
+ extern Key cxx_epilogue;
+ extern Key epilogue;
+ extern Key hxx_prologue_file;
+ extern Key ixx_prologue_file;
+ extern Key cxx_prologue_file;
+ extern Key prologue_file;
+ extern Key hxx_epilogue_file;
+ extern Key ixx_epilogue_file;
+ extern Key cxx_epilogue_file;
+ extern Key epilogue_file;
+ extern Key show_anonymous;
+ extern Key show_sloc;
+ extern Key proprietary_license;
+
+ typedef Cult::CLI::Options<
+ type_map, Cult::Containers::Vector<NarrowString>,
+ no_stl, Boolean,
+ no_iostream, Boolean,
+ no_exceptions, Boolean,
+ no_long_long, Boolean,
+ reuse_style_mixin, Boolean,
+ reuse_style_none, Boolean,
+ generate_inline, Boolean,
+ suppress_validation, Boolean,
+ generate_polymorphic, Boolean,
+ runtime_polymorphic, Boolean,
+ suppress_reset, Boolean,
+ generate_empty_impl, Boolean,
+ generate_test_driver, Boolean,
+ force_overwrite, Boolean,
+ root_element_first, Boolean,
+ root_element_last, Boolean,
+ root_element, NarrowString,
+ generate_xml_schema, Boolean,
+ extern_xml_schema, NarrowString,
+ output_dir, NarrowString,
+ skel_type_suffix, NarrowString,
+ skel_file_suffix, NarrowString,
+ impl_type_suffix, NarrowString,
+ impl_file_suffix, NarrowString,
+ namespace_map, Cult::Containers::Vector<NarrowString>,
+ namespace_regex, Cult::Containers::Vector<NarrowString>,
+ namespace_regex_trace, Boolean,
+ reserved_name, Cult::Containers::Vector<NarrowString>,
+ include_with_brackets, Boolean,
+ include_prefix, NarrowString,
+ include_regex, Cult::Containers::Vector<NarrowString>,
+ include_regex_trace, Boolean,
+ guard_prefix, NarrowString,
+ hxx_suffix, NarrowString,
+ ixx_suffix, NarrowString,
+ cxx_suffix, NarrowString,
+ hxx_regex, NarrowString,
+ ixx_regex, NarrowString,
+ cxx_regex, NarrowString,
+ hxx_prologue, Cult::Containers::Vector<NarrowString>,
+ ixx_prologue, Cult::Containers::Vector<NarrowString>,
+ cxx_prologue, Cult::Containers::Vector<NarrowString>,
+ prologue, Cult::Containers::Vector<NarrowString>,
+ hxx_epilogue, Cult::Containers::Vector<NarrowString>,
+ ixx_epilogue, Cult::Containers::Vector<NarrowString>,
+ cxx_epilogue, Cult::Containers::Vector<NarrowString>,
+ epilogue, Cult::Containers::Vector<NarrowString>,
+ hxx_prologue_file, NarrowString,
+ ixx_prologue_file, NarrowString,
+ cxx_prologue_file, NarrowString,
+ prologue_file, NarrowString,
+ hxx_epilogue_file, NarrowString,
+ ixx_epilogue_file, NarrowString,
+ cxx_epilogue_file, NarrowString,
+ epilogue_file, NarrowString,
+ show_anonymous, Boolean,
+ show_sloc, Boolean,
+ proprietary_license, Boolean
+
+ > Options;
+
+ struct OptionsSpec: Cult::CLI::OptionsSpec<Options> {};
+ }
+ }
+}
+
+#endif // CXX_SERIALIZER_CLI_HXX
diff --git a/xsde/cxx/serializer/driver-source.cxx b/xsde/cxx/serializer/driver-source.cxx
new file mode 100644
index 0000000..4a3c7db
--- /dev/null
+++ b/xsde/cxx/serializer/driver-source.cxx
@@ -0,0 +1,1047 @@
+// file : xsde/cxx/serializer/driver-source.cxx
+// author : Boris Kolpackov <boris@codesynthesis.com>
+// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC
+// license : GNU GPL v2 + exceptions; see accompanying LICENSE file
+
+#include <cxx/serializer/driver-source.hxx>
+
+#include <xsd-frontend/semantic-graph.hxx>
+#include <xsd-frontend/traversal.hxx>
+
+#include <cult/containers/map.hxx>
+#include <cult/containers/set.hxx>
+
+#include <sstream>
+
+namespace CXX
+{
+ namespace Serializer
+ {
+ namespace
+ {
+ typedef
+ Cult::Containers::Map<SemanticGraph::Type*, String>
+ TypeInstanceMap;
+
+ typedef Cult::Containers::Set<String> InstanceSet;
+
+ // For base types we only want member's types, but not the
+ // base itself.
+ //
+ struct BaseType: Traversal::Complex, Context
+ {
+ BaseType (Context& c)
+ : Context (c)
+ {
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Complex& c)
+ {
+ inherits (c);
+
+ if (!restriction_p (c))
+ {
+ names (c);
+ contains_compositor (c);
+ }
+ }
+ };
+
+ struct SerializerDef: Traversal::Type,
+ Traversal::List,
+ Traversal::Complex,
+
+ Traversal::AnyType,
+ Traversal::AnySimpleType,
+
+ Traversal::Fundamental::Byte,
+ Traversal::Fundamental::UnsignedByte,
+ Traversal::Fundamental::Short,
+ Traversal::Fundamental::UnsignedShort,
+ Traversal::Fundamental::Int,
+ Traversal::Fundamental::UnsignedInt,
+ Traversal::Fundamental::Long,
+ Traversal::Fundamental::UnsignedLong,
+ Traversal::Fundamental::Integer,
+ Traversal::Fundamental::NonPositiveInteger,
+ Traversal::Fundamental::NonNegativeInteger,
+ Traversal::Fundamental::PositiveInteger,
+ Traversal::Fundamental::NegativeInteger,
+
+ Traversal::Fundamental::Boolean,
+
+ Traversal::Fundamental::Float,
+ Traversal::Fundamental::Double,
+ Traversal::Fundamental::Decimal,
+
+ Traversal::Fundamental::String,
+ Traversal::Fundamental::NormalizedString,
+ Traversal::Fundamental::Token,
+ Traversal::Fundamental::Name,
+ Traversal::Fundamental::NameToken,
+ Traversal::Fundamental::NameTokens,
+ Traversal::Fundamental::NCName,
+ Traversal::Fundamental::Language,
+
+ Traversal::Fundamental::QName,
+
+ Traversal::Fundamental::Id,
+ Traversal::Fundamental::IdRef,
+ Traversal::Fundamental::IdRefs,
+
+ Traversal::Fundamental::AnyURI,
+
+ Traversal::Fundamental::Base64Binary,
+ Traversal::Fundamental::HexBinary,
+
+ Traversal::Fundamental::Date,
+ Traversal::Fundamental::DateTime,
+ Traversal::Fundamental::Duration,
+ Traversal::Fundamental::Day,
+ Traversal::Fundamental::Month,
+ Traversal::Fundamental::MonthDay,
+ Traversal::Fundamental::Year,
+ Traversal::Fundamental::YearMonth,
+ Traversal::Fundamental::Time,
+
+ Traversal::Fundamental::Entity,
+ Traversal::Fundamental::Entities,
+
+ Context
+ {
+ SerializerDef (Context& c, TypeInstanceMap& map, InstanceSet& set)
+ : Context (c), map_ (map), set_ (set), base_ (c)
+ {
+ *this >> inherits_ >> base_ >> inherits_;
+
+ *this >> contains_compositor_;
+ base_ >> contains_compositor_;
+
+ *this >> names_;
+ base_ >> names_;
+
+ contains_compositor_ >> compositor_;
+ compositor_ >> contains_particle_;
+ contains_particle_ >> compositor_;
+ contains_particle_ >> particle_;
+
+ names_ >> attribute_;
+
+ particle_ >> belongs_;
+ attribute_ >> belongs_;
+ belongs_ >> *this;
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Type& t)
+ {
+ if (map_.find (&t) == map_.end ())
+ {
+ String inst (find_instance_name (t));
+ map_[&t] = inst;
+
+ os << fq_name (t, "s:impl") << " " << inst << ";";
+ }
+ }
+
+ virtual Void
+ traverse (SemanticGraph::List& l)
+ {
+ if (map_.find (&l) == map_.end ())
+ {
+ String inst (find_instance_name (l));
+ map_[&l] = inst;
+
+ os << fq_name (l, "s:impl") << " " << inst << ";";
+
+ dispatch (l.argumented ().type ());
+ }
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Complex& c)
+ {
+ if (map_.find (&c) == map_.end ())
+ {
+ String inst (find_instance_name (c));
+ map_[&c] = inst;
+
+ os << fq_name (c, "s:impl") << " " << inst << ";";
+
+ inherits (c);
+
+ if (!restriction_p (c))
+ {
+ names (c);
+ contains_compositor (c);
+ }
+ }
+ }
+
+ // anyType & anySimpleType.
+ //
+ virtual Void
+ traverse (SemanticGraph::AnyType& t)
+ {
+ fund_type (t, "any_type");
+ }
+
+ virtual Void
+ traverse (SemanticGraph::AnySimpleType& t)
+ {
+ fund_type (t, "any_simple_type");
+ }
+
+ // Boolean.
+ //
+ virtual Void
+ traverse (SemanticGraph::Fundamental::Boolean& t)
+ {
+ fund_type (t, "boolean");
+ }
+
+ // Integral types.
+ //
+ virtual Void
+ traverse (SemanticGraph::Fundamental::Byte& t)
+ {
+ fund_type (t, "byte");
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::UnsignedByte& t)
+ {
+ fund_type (t, "unsigned_byte");
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::Short& t)
+ {
+ fund_type (t, "short");
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::UnsignedShort& t)
+ {
+ fund_type (t, "unsigned_short");
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::Int& t)
+ {
+ fund_type (t, "int");
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::UnsignedInt& t)
+ {
+ fund_type (t, "unsigned_int");
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::Long& t)
+ {
+ fund_type (t, "long");
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::UnsignedLong& t)
+ {
+ fund_type (t, "unsigned_long");
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::Integer& t)
+ {
+ fund_type (t, "integer");
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::NonPositiveInteger& t)
+ {
+ fund_type (t, "non_positive_integer");
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::NonNegativeInteger& t)
+ {
+ fund_type (t, "non_negative_integer");
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::PositiveInteger& t)
+ {
+ fund_type (t, "positive_integer");
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::NegativeInteger& t)
+ {
+ fund_type (t, "negative_integer");
+ }
+
+ // Floats.
+ //
+ virtual Void
+ traverse (SemanticGraph::Fundamental::Float& t)
+ {
+ fund_type (t, "float");
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::Double& t)
+ {
+ fund_type (t, "double");
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::Decimal& t)
+ {
+ fund_type (t, "decimal");
+ }
+
+ // Strings.
+ //
+ virtual Void
+ traverse (SemanticGraph::Fundamental::String& t)
+ {
+ fund_type (t, "string");
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::NormalizedString& t)
+ {
+ fund_type (t, "normalized_string");
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::Token& t)
+ {
+ fund_type (t, "token");
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::NameToken& t)
+ {
+ fund_type (t, "nmtoken");
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::NameTokens& t)
+ {
+ fund_type (t, "nmtokens");
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::Name& t)
+ {
+ fund_type (t, "name");
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::NCName& t)
+ {
+ fund_type (t, "ncname");
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::Language& t)
+ {
+ fund_type (t, "language");
+ }
+
+
+ // Qualified name.
+ //
+ virtual Void
+ traverse (SemanticGraph::Fundamental::QName& t)
+ {
+ fund_type (t, "qname");
+ }
+
+
+ // ID/IDREF.
+ //
+ virtual Void
+ traverse (SemanticGraph::Fundamental::Id& t)
+ {
+ fund_type (t, "id");
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::IdRef& t)
+ {
+ fund_type (t, "idref");
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::IdRefs& t)
+ {
+ fund_type (t, "idrefs");
+ }
+
+ // URI.
+ //
+ virtual Void
+ traverse (SemanticGraph::Fundamental::AnyURI& t)
+ {
+ fund_type (t, "uri");
+ }
+
+ // Binary.
+ //
+ virtual Void
+ traverse (SemanticGraph::Fundamental::Base64Binary& t)
+ {
+ fund_type (t, "base64_binary");
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::HexBinary& t)
+ {
+ fund_type (t, "hex_binary");
+ }
+
+
+ // Date/time.
+ //
+ virtual Void
+ traverse (SemanticGraph::Fundamental::Date& t)
+ {
+ fund_type (t, "date");
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::DateTime& t)
+ {
+ fund_type (t, "date_time");
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::Duration& t)
+ {
+ fund_type (t, "duration");
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::Day& t)
+ {
+ fund_type (t, "day");
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::Month& t)
+ {
+ fund_type (t, "month");
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::MonthDay& t)
+ {
+ fund_type (t, "month_day");
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::Year& t)
+ {
+ fund_type (t, "year");
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::YearMonth& t)
+ {
+ fund_type (t, "year_month");
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::Time& t)
+ {
+ fund_type (t, "time");
+ }
+
+ // Entity.
+ //
+ virtual Void
+ traverse (SemanticGraph::Fundamental::Entity& t)
+ {
+ fund_type (t, "entity");
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::Entities& t)
+ {
+ fund_type (t, "entities");
+ }
+
+ private:
+ virtual Void
+ fund_type (SemanticGraph::Type& t, String const& name)
+ {
+ if (map_.find (&t) == map_.end ())
+ {
+ String inst (find_instance_name (name));
+ map_[&t] = inst;
+
+ os << fq_name (t, "s:impl") << " " << inst << ";";
+ }
+ }
+
+ String
+ find_instance_name (String const& raw_name)
+ {
+ String base_name (escape (raw_name + L"_s"));
+ String name (base_name);
+
+ for (UnsignedLong i (1); set_.find (name) != set_.end (); ++i)
+ {
+ std::wostringstream os;
+ os << i;
+ name = base_name + os.str ();
+ }
+
+ set_.insert (name);
+ return name;
+ }
+
+ String
+ find_instance_name (SemanticGraph::Type& t)
+ {
+ return find_instance_name (t.name ());
+ }
+
+ TypeInstanceMap& map_;
+ InstanceSet& set_;
+
+ BaseType base_;
+ Traversal::Inherits inherits_;
+
+ Traversal::Compositor compositor_;
+ Traversal::Element particle_;
+ Traversal::ContainsCompositor contains_compositor_;
+ Traversal::ContainsParticle contains_particle_;
+
+ Traversal::Names names_;
+ Traversal::Attribute attribute_;
+
+ Traversal::Belongs belongs_;
+ };
+
+ //
+ //
+ struct ParticleArg: Traversal::Element, Context
+ {
+ ParticleArg (Context& c, TypeInstanceMap& map, Boolean& first)
+ : Context (c), map_ (map), first_ (first)
+ {
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Element& e)
+ {
+ if (!first_)
+ os << "," << endl;
+ else
+ first_ = false;
+
+ os << map_[&e.type ()];
+ }
+
+ private:
+ TypeInstanceMap& map_;
+ Boolean& first_;
+ };
+
+ struct AttributeArg: Traversal::Attribute, Context
+ {
+ AttributeArg (Context& c, TypeInstanceMap& map, Boolean& first)
+ : Context (c), map_ (map), first_ (first)
+ {
+ }
+
+ virtual Void
+ traverse (Type& a)
+ {
+ if (!first_)
+ os << "," << endl;
+ else
+ first_ = false;
+
+ os << map_[&a.type ()];
+ }
+
+ private:
+ TypeInstanceMap& map_;
+ Boolean& first_;
+ };
+
+ struct ArgList : Traversal::Complex,
+ Traversal::List,
+ Context
+ {
+ ArgList (Context& c, TypeInstanceMap& map)
+ : Context (c),
+ map_ (map),
+ particle_ (c, map, first_),
+ attribute_ (c, map, first_),
+ first_ (true)
+ {
+ inherits_ >> *this;
+
+ contains_compositor_ >> compositor_;
+ compositor_ >> contains_particle_;
+ contains_particle_ >> compositor_;
+ contains_particle_ >> particle_;
+
+ names_ >> attribute_;
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Complex& c)
+ {
+ inherits (c, inherits_);
+
+ if (!restriction_p (c))
+ {
+ names (c, names_);
+ contains_compositor (c, contains_compositor_);
+ }
+ }
+
+ virtual Void
+ traverse (SemanticGraph::List& l)
+ {
+ if (!first_)
+ os << "," << endl;
+ else
+ first_ = false;
+
+ os << map_[&l.argumented ().type ()];
+ }
+
+ private:
+ TypeInstanceMap& map_;
+
+ Traversal::Inherits inherits_;
+
+ Traversal::Compositor compositor_;
+ ParticleArg particle_;
+ Traversal::ContainsCompositor contains_compositor_;
+ Traversal::ContainsParticle contains_particle_;
+
+ Traversal::Names names_;
+ AttributeArg attribute_;
+
+ Boolean first_;
+ };
+
+ struct SerializerConnect: Traversal::List,
+ Traversal::Complex,
+ Context
+ {
+ SerializerConnect (Context& c, TypeInstanceMap& map)
+ : Context (c), map_ (map), base_ (c)
+ {
+ *this >> inherits_ >> base_ >> inherits_;
+
+ *this >> contains_compositor_;
+ base_ >> contains_compositor_;
+
+ *this >> names_;
+ base_ >> names_;
+
+ contains_compositor_ >> compositor_;
+ compositor_ >> contains_particle_;
+ contains_particle_ >> compositor_;
+ contains_particle_ >> particle_;
+
+ names_ >> attribute_;
+
+ particle_ >> belongs_;
+ attribute_ >> belongs_;
+ belongs_ >> *this;
+ }
+
+ virtual Void
+ traverse (SemanticGraph::List& l)
+ {
+ if (type_set_.find (&l) == type_set_.end ())
+ {
+ os << map_[&l] << ".serializers (" <<
+ map_[&l.argumented ().type ()] << ");"
+ << endl;
+
+ type_set_.insert (&l);
+ }
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Complex& c)
+ {
+ if (type_set_.find (&c) == type_set_.end ())
+ {
+ if (has_members (c))
+ {
+ os << map_[&c] << ".serializers (";
+
+ ArgList args (*this, map_);
+ args.dispatch (c);
+
+ os << ");"
+ << endl;
+ }
+
+ type_set_.insert (&c);
+
+ inherits (c);
+
+ if (!restriction_p (c))
+ {
+ names (c);
+ contains_compositor (c);
+ }
+ }
+ }
+
+ private:
+ Boolean
+ has_members (SemanticGraph::Complex& c)
+ {
+ using SemanticGraph::Complex;
+
+ if (has<Traversal::Member> (c))
+ return true;
+
+ if (c.inherits_p ())
+ {
+ SemanticGraph::Type& b (c.inherits ().base ());
+
+ if (Complex* cb = dynamic_cast<Complex*> (&b))
+ return has_members (*cb);
+
+ return b.is_a<SemanticGraph::List> ();
+ }
+
+ return false;
+ }
+
+ private:
+ TypeInstanceMap& map_;
+ Cult::Containers::Set<SemanticGraph::Type*> type_set_;
+
+ BaseType base_;
+ Traversal::Inherits inherits_;
+
+ Traversal::Compositor compositor_;
+ Traversal::Element particle_;
+ Traversal::ContainsCompositor contains_compositor_;
+ Traversal::ContainsParticle contains_particle_;
+
+ Traversal::Names names_;
+ Traversal::Attribute attribute_;
+
+ Traversal::Belongs belongs_;
+ };
+
+ struct GlobalElement: Traversal::Element, Context
+ {
+ GlobalElement (Context& c, SemanticGraph::Element*& element)
+ : Context (c), element_ (element)
+ {
+ }
+
+ virtual Void
+ traverse (Type& e)
+ {
+ if (options.value<CLI::root_element_first> ())
+ {
+ if (element_ == 0)
+ element_ = &e;
+ }
+ else if (String name = options.value<CLI::root_element> ())
+ {
+ if (e.name () == name)
+ element_ = &e;
+ }
+ else
+ element_ = &e; // Cover root-element-last and no option.
+ }
+
+ private:
+ SemanticGraph::Element*& element_;
+ };
+ }
+
+ Void
+ generate_driver_source (Context& ctx)
+ {
+ // Figure out the root element. Validator should have made sure
+ // it is unique.
+ //
+ SemanticGraph::Element* root (0);
+ {
+ Traversal::Schema schema;
+ Traversal::Sources sources;
+
+ schema >> sources >> schema;
+
+ Traversal::Names schema_names;
+ Traversal::Namespace ns;
+ Traversal::Names ns_names;
+ RootElement global_element (ctx.options, root);
+
+ schema >> schema_names >> ns >> ns_names >> global_element;
+
+ schema.dispatch (ctx.schema_root);
+ }
+
+ String xs (ctx.xs_ns_name ());
+ std::wostream& os (ctx.os);
+
+ InstanceSet set;
+ TypeInstanceMap map;
+ SemanticGraph::Type& root_type (root->type ());
+
+ set.insert ("doc_s");
+
+ if (ctx.options.value<CLI::no_iostream> ())
+ os << "#include <stdio.h>" << endl
+ << endl;
+ else
+ os << "#include <iostream>" << endl
+ << endl;
+
+ if (ctx.options.value<CLI::no_iostream> ())
+ {
+ if (ctx.options.value<CLI::no_exceptions> ())
+ {
+ os << "struct writer: " << xs << "::writer"
+ << "{"
+ << "virtual bool" << endl
+ << "write (const char* s, size_t n)"
+ << "{"
+ << "return fwrite (s, n, 1, stdout) == 1;"
+ << "}"
+ << "virtual bool" << endl
+ << "flush ()"
+ << "{"
+ << "return fflush (stdout) == 0;"
+ << "}"
+ << "};";
+ }
+ else
+ {
+ os << "struct io_failure"
+ << "{"
+ << "};";
+
+ os << "struct writer: " << xs << "::writer"
+ << "{"
+ << "virtual void" << endl
+ << "write (const char* s, size_t n)"
+ << "{"
+ << "if (fwrite (s, n, 1, stdout) != 1)" << endl
+ << "throw io_failure ();"
+ << "}"
+ << "virtual void" << endl
+ << "flush ()"
+ << "{"
+ << "if (fflush (stdout) != 0)" << endl
+ << "throw io_failure ();"
+ << "}"
+ << "};";
+ }
+ }
+
+ os << "int" << endl
+ << "main ()"
+ << "{";
+
+ if (!ctx.options.value<CLI::no_exceptions> ())
+ os << "try"
+ << "{";
+
+ os << "// Instantiate individual serializers." << endl
+ << "//" << endl;
+
+ {
+ SerializerDef def (ctx, map, set);
+ def.dispatch (root_type);
+ }
+
+ os << endl
+ << "// Connect the serializers together." << endl
+ << "//" << endl;
+
+ {
+ // @@ I can simply iterate over the map instead of traversing
+ // the tree all over again.
+ //
+ SerializerConnect connect (ctx, map);
+ connect.dispatch (root_type);
+ }
+
+ String const& root_s (map[&root_type]);
+
+ os << "// Serialize the XML document." << endl
+ << "//" << endl;
+
+ if (ctx.options.value<CLI::no_iostream> ())
+ os << "writer w;";
+
+ if (ctx.options.value<CLI::no_exceptions> ())
+ os << xs << "::serializer_error e;"
+ << endl
+ << "do"
+ << "{";
+
+ if (root->namespace_().name ())
+ os << xs << "::document_simpl doc_s (" << endl
+ << root_s << "," << endl
+ << ctx.strlit (root->namespace_().name ()) << "," << endl
+ << ctx.strlit (root->name ()) << ");"
+ << endl;
+ else
+ os << xs << "::document_simpl doc_s (" << root_s << ", " <<
+ ctx.strlit (root->name ()) << ");"
+ << endl;
+
+ if (ctx.options.value<CLI::no_exceptions> ())
+ os << "if (e = doc_s._error ())" << endl
+ << "break;"
+ << endl;
+
+ if (Context::arg_type (root->type ()) != L"void")
+ os << "// TODO: pass the " << root->name () << " element data " <<
+ "to pre()" << endl
+ << "//" << endl;
+
+ os << root_s << ".pre ();"
+ << endl;
+
+ if (ctx.options.value<CLI::no_exceptions> ())
+ os << "if (e = " << root_s << "._error ())" << endl
+ << "break;"
+ << endl;
+
+ if (ctx.options.value<CLI::no_iostream> ())
+ os << "doc_s.serialize (w);"
+ << endl;
+ else
+ os << "doc_s.serialize (std::cout);"
+ << endl;
+
+ if (ctx.options.value<CLI::no_exceptions> ())
+ os << "if (e = doc_s._error ())" << endl
+ << "break;"
+ << endl;
+
+ os << root_s << ".post ();";
+
+ if (ctx.options.value<CLI::no_exceptions> ())
+ os << endl
+ << "e = " << root_s << "._error ();";
+
+ if (ctx.options.value<CLI::no_exceptions> ())
+ os << "}"
+ << "while (false);"
+ << endl;
+
+ // Error handling.
+ //
+
+ if (ctx.options.value<CLI::no_exceptions> ())
+ {
+ os << "// Handle errors." << endl
+ << "//" << endl
+ << "if (e)"
+ << "{"
+ << "switch (e.type ())"
+ << "{"
+ << "case " << xs << "::serializer_error::sys:"
+ << "{";
+
+ if (ctx.options.value<CLI::no_iostream> ())
+ os << "fprintf (stderr, \"%s\\n\", e.sys_text ());";
+ else
+ os << "std::cerr << e.sys_text () << std::endl;";
+
+ os << "break;"
+ << "}"
+ << "case " << xs << "::serializer_error::xml:"
+ << "{";
+
+ if (ctx.options.value<CLI::no_iostream> ())
+ os << "fprintf (stderr, \"%s\\n\", e.xml_text ());";
+ else
+ os << "std::cerr << e.xml_text () << std::endl;";
+
+ os << "break;"
+ << "}";
+
+ if (!ctx.options.value<CLI::suppress_validation> ())
+ {
+ os << "case " << xs << "::serializer_error::schema:"
+ << "{";
+
+ if (ctx.options.value<CLI::no_iostream> ())
+ os << "fprintf (stderr, \"%s\\n\", e.schema_text ());";
+ else
+ os << "std::cerr << e.schema_text () << std::endl;";
+
+ os << "break;"
+ << "}";
+ }
+
+ os << "case " << xs << "::serializer_error::app:"
+ << "{";
+
+ if (ctx.options.value<CLI::no_iostream> ())
+ os << "fprintf (stderr, \"application error %d\\n\", e.app_code ());";
+ else
+ os << "std::cerr << \"application error \" << e.app_code () " <<
+ "<< std::endl;";
+
+ os << "break;"
+ << "}"
+ << "default:"
+ << "{"
+ << "break;"
+ << "}"
+ << "}" //switch
+ << "return 1;"
+ << "}"; // if (e)
+ }
+ else
+ {
+ os << "}" // try
+ << "catch (const " << xs << "::serializer_exception& e)"
+ << "{";
+
+ if (ctx.options.value<CLI::no_iostream> ())
+ os << "fprintf (stderr, \"error: %s\\n\", e.text ());";
+ else
+ os << "std::cerr << \"error: \" << e.text () << std::endl;";
+
+ os << "return 1;"
+ << "}";
+
+ if (ctx.options.value<CLI::no_iostream> ())
+ os << "catch (const io_failure&)"
+ << "{"
+ << "fprintf (stderr, \"error: write failure\\n\");"
+ << "return 1;"
+ << "}";
+ else
+ os << "catch (const std::ios_base::failure&)"
+ << "{"
+ << "std::cerr << \"error: write failure\" << std::endl;"
+ << "return 1;"
+ << "}";
+ }
+
+ os << "return 0;"
+ << "}"; // main
+ }
+ }
+}
diff --git a/xsde/cxx/serializer/driver-source.hxx b/xsde/cxx/serializer/driver-source.hxx
new file mode 100644
index 0000000..b29cf34
--- /dev/null
+++ b/xsde/cxx/serializer/driver-source.hxx
@@ -0,0 +1,22 @@
+// file : xsde/cxx/serializer/driver-source.hxx
+// author : Boris Kolpackov <boris@codesynthesis.com>
+// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC
+// license : GNU GPL v2 + exceptions; see accompanying LICENSE file
+
+#ifndef CXX_SERIALIZER_DRIVER_SOURCE_HXX
+#define CXX_SERIALIZER_DRIVER_SOURCE_HXX
+
+#include <xsd-frontend/semantic-graph/schema.hxx>
+
+#include <cxx/serializer/elements.hxx>
+
+namespace CXX
+{
+ namespace Serializer
+ {
+ Void
+ generate_driver_source (Context&);
+ }
+}
+
+#endif // CXX_SERIALIZER_DRIVER_SOURCE_HXX
diff --git a/xsde/cxx/serializer/element-validation-source.cxx b/xsde/cxx/serializer/element-validation-source.cxx
new file mode 100644
index 0000000..fd0dfb4
--- /dev/null
+++ b/xsde/cxx/serializer/element-validation-source.cxx
@@ -0,0 +1,903 @@
+// file : xsde/cxx/serializer/element-validation-source.cxx
+// author : Boris Kolpackov <boris@codesynthesis.com>
+// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC
+// license : GNU GPL v2 + exceptions; see accompanying LICENSE file
+
+#include <cxx/serializer/element-validation-source.hxx>
+
+#include <xsd-frontend/semantic-graph.hxx>
+#include <xsd-frontend/traversal.hxx>
+
+namespace CXX
+{
+ namespace Serializer
+ {
+ namespace
+ {
+ struct AnyTest: Traversal::Any, Context
+ {
+ AnyTest (Context& c)
+ : Context (c)
+ {
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Any& a)
+ {
+ String const& ns (a.definition_namespace ().name ());
+
+ for (SemanticGraph::Any::NamespaceIterator i (a.namespace_begin ()),
+ e (a.namespace_end ()); i != e;)
+ {
+ if (*i == L"##any")
+ {
+ if (stl)
+ os << "!name.empty ()";
+ else
+ os << "(name != 0 && *name != '\\0')";
+ }
+ else if (*i == L"##other")
+ {
+ if (ns)
+ {
+ // Note that here I assume that ##other does not include
+ // unqualified names in a schema with target namespace.
+ // This is not what the spec says but that seems to be
+ // the consensus.
+ //
+ if (stl)
+ os << "(!ns.empty () && ns != " << strlit (ns) << ")";
+ else
+ os << "(ns != 0 && *ns != '\\0' && " <<
+ "strcmp (ns, " << strlit (ns) << ") != 0)";
+ }
+ else
+ {
+ if (stl)
+ os << "!ns.empty ()";
+ else
+ os << "(ns != 0 && *ns != '\\0')";
+ }
+ }
+ else if (*i == L"##local")
+ {
+ if (stl)
+ os << "(ns.empty () && !name.empty ())";
+ else
+ os << "((ns == 0 || *ns == '\\0') && " <<
+ "name != 0 && *name != '\\0')";
+ }
+ else if (*i == L"##targetNamespace")
+ {
+ if (stl)
+ os << "ns == " << strlit (ns);
+ else
+ os << "(ns != 0 && strcmp (ns, " << strlit (ns) << ") == 0)";
+ }
+ else
+ {
+ if (stl)
+ os << "ns == " << strlit (*i);
+ else
+ os << "(ns != 0 && strcmp (ns, " << strlit (*i) << ") == 0)";
+ }
+
+ if (++i != e)
+ os << " ||" << endl;
+ }
+ }
+ };
+
+ struct Compositor: Traversal::All,
+ Traversal::Choice,
+ Traversal::Sequence,
+ Context
+ {
+ Compositor (Context& c)
+ : Context (c)
+ {
+ }
+
+ virtual Void
+ traverse (SemanticGraph::All& a)
+ {
+ // For the all compositor, maxOccurs=1 and minOccurs={0,1}.
+ //
+ UnsignedLong min (a.min ());
+
+ if (min == 0)
+ os << "if (this->" << epresent (a) << " ())"
+ << "{";
+
+ Traversal::All::traverse (a);
+
+ if (min == 0)
+ {
+ os << "}";
+
+ if (!exceptions)
+ os << "if (ctx.error_type ())" << endl
+ << "return;"
+ << endl;
+ }
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Choice& c)
+ {
+ if (c.contains_begin () != c.contains_end ())
+ {
+ UnsignedLong min (c.min ()), max (c.max ());
+
+ if (min == 0 && max == 1)
+ {
+ os << "if (this->" << epresent (c) << " ())"
+ << "{";
+ }
+ else if (max != 1)
+ {
+ // We only need to count if max != unbounded || min != 0.
+ //
+ if (max != 0 || min != 0)
+ {
+ os << "{"
+ << "size_t i = 0;"
+ << "for (; ";
+
+ if (max != 0)
+ os << "i < " << max << "UL && ";
+
+ os << "this->" << enext (c) << " (); ++i)"
+ << "{";
+ }
+ else
+ os << "while (this->" << enext (c) << " ())"
+ << "{";
+ }
+ else if (!exceptions)
+ {
+ // Only sequence can have several choice compositors in a row.
+ //
+ os << "{";
+ }
+
+ if (exceptions)
+ os << "switch (this->" << earm (c) << " ())";
+ else
+ os << earm_tag (c) << " t = this->" << earm (c) << " ();"
+ << endl
+ << "if (ctx.error_type ())" << endl
+ << "return;"
+ << endl
+ << "switch (t)";
+
+
+ os << "{";
+
+ for (SemanticGraph::Choice::ContainsIterator
+ i (c.contains_begin ()); i != c.contains_end (); ++i)
+ {
+ os << "case " << etag (i->particle ()) << ":"
+ << "{";
+
+ edge_traverser ().dispatch (*i);
+
+ os << "break;"
+ << "}";
+ }
+
+ os << "default:"
+ << "{"
+ << "this->_schema_error (" <<
+ "::xsde::cxx::schema_error::unexpected_element);"
+ << "return;"
+ << "}"
+ << "}"; // switch
+
+ if (min == 0 && max == 1)
+ {
+ os << "}";
+
+ if (!exceptions)
+ os << "if (ctx.error_type ())" << endl
+ << "return;"
+ << endl;
+ }
+ else if (max != 1)
+ {
+ os << "}";
+
+ if (!exceptions)
+ os << "if (ctx.error_type ())" << endl
+ << "return;"
+ << endl;
+
+ if (max != 0 || min != 0)
+ {
+ if (min != 0)
+ {
+ os << "if (i < " << min << "UL)"
+ << "{"
+ << "this->_schema_error (" <<
+ "::xsde::cxx::schema_error::expected_element);"
+ << "return;"
+ << "}";
+ }
+
+ os << "}";
+ }
+ }
+ else if (!exceptions)
+ {
+ os << "}";
+ }
+ }
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Sequence& s)
+ {
+ UnsignedLong min (s.min ()), max (s.max ());
+
+ if (min == 0 && max == 1)
+ {
+ os << "if (this->" << epresent (s) << " ())"
+ << "{";
+ }
+ else if (max != 1)
+ {
+ // We only need to count if max != unbounded || min != 0.
+ //
+ if (max != 0 || min != 0)
+ {
+ os << "{"
+ << "size_t i = 0;"
+ << "for (; ";
+
+ if (max != 0)
+ os << "i < " << max << "UL && ";
+
+ os << "this->" << enext (s) << " (); ++i)"
+ << "{";
+ }
+ else
+ os << "while (this->" << enext (s) << " ())"
+ << "{";
+ }
+
+ Traversal::Sequence::traverse (s);
+
+ if (min == 0 && max == 1)
+ {
+ os << "}";
+
+ if (!exceptions)
+ os << "if (ctx.error_type ())" << endl
+ << "return;"
+ << endl;
+ }
+ else if (max != 1)
+ {
+ os << "}";
+
+ if (!exceptions)
+ os << "if (ctx.error_type ())" << endl
+ << "return;"
+ << endl;
+
+ if (max != 0 || min != 0)
+ {
+ if (min != 0)
+ {
+ os << "if (i < " << min << "UL)"
+ << "{"
+ << "this->_schema_error (" <<
+ "::xsde::cxx::schema_error::expected_element);"
+ << "return;"
+ << "}";
+ }
+
+ os << "}";
+ }
+ }
+ }
+ };
+
+ struct Particle: Traversal::Element,
+ Traversal::Any,
+ Context
+ {
+ Particle (Context& c)
+ : Context (c), any_test_ (c)
+ {
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Element& e)
+ {
+ UnsignedLong min (e.min ()), max (e.max ());
+
+ String const& name (ename (e));
+
+ os << "// " << name << endl
+ << "//" << endl;
+
+ if (min == 0 && max == 1)
+ {
+ os << "if (this->" << epresent (e) << " ())";
+ }
+ else if (max != 1)
+ {
+ // We only need to count if max != unbounded || min != 0.
+ //
+ if (max != 0 || min != 0)
+ {
+ os << "{"
+ << "size_t i = 0;"
+ << "for (; ";
+
+ if (max != 0)
+ os << "i < " << max << "UL && ";
+
+ os << "this->" << enext (e) << " (); ++i)";
+ }
+ else
+ os << "while (this->" << enext (e) << " ())";
+ }
+
+ os << "{";
+
+ String const& ret (ret_type (e.type ()));
+ String const& arg (arg_type (e.type ()));
+ String fq_type (fq_name (e.type ()));
+
+ Boolean poly (poly_code && !anonymous (e.type ()));
+ String inst (poly ? String (L"s") : L"this->" + emember (e));
+
+ if (poly)
+ os << "ctx.type_id (0);";
+
+ if (ret == L"void")
+ os << "this->" << name << " ();"
+ << endl;
+ else
+ os << arg << " r = this->" << name << " ();"
+ << endl;
+
+ if (!exceptions)
+ os << "if (ctx.error_type ())" << endl
+ << "return;"
+ << endl;
+
+ if (poly)
+ {
+ // In case of mixin we use virtual inheritance and only
+ // dynamic_cast can be used.
+ //
+ String cast (mixin ? L"dynamic_cast" : L"static_cast");
+
+ os << "const void* t = ctx.type_id ();"
+ << "const char* dt = 0;"
+ << fq_type << "* " << inst << " = 0;"
+ << endl
+ << "if (t == 0 && this->" << emember (e) << " != 0)" << endl
+ << inst << " = this->" << emember (e) << ";"
+ << "else if (this->" << emember_map (e) << " != 0)"
+ << "{"
+ << serializer_base << "* b = this->" << emember_map (e) <<
+ "->find (t);"
+ << endl
+ << "if (b != 0)"
+ << "{"
+ << "dt = b->_dynamic_type ();"
+ << "const char* st = " << fq_type << "::_static_type ();"
+ << endl
+ << "if (strcmp (dt, st) == 0)" << endl
+ << "dt = 0;"
+ << endl;
+
+ // Check that the types are related by inheritance.
+ //
+ os << "if (dt != 0 && !::xsde::cxx::serializer::validating::" <<
+ "inheritance_map_instance ().check (dt, st))"
+ << "{"
+ << "ctx.schema_error (::xsde::cxx::schema_error::not_derived);"
+ << "return;"
+ << "}";
+
+ os << inst << " = " << cast << "< " << fq_type << "* > (b);"
+ << "}"
+ << "}";
+ }
+
+ os << "if (" << inst << ")"
+ << "{";
+
+ if (ret == L"void")
+ os << inst << "->pre ();";
+ else
+ os << inst << "->pre (r);";
+
+ if (!exceptions)
+ {
+ // Note that after pre() we need to check both parser and
+ // context error states because of the recursive parsing.
+ //
+ os << endl
+ << "if (" << inst << "->_error_type ())" << endl
+ << inst << "->_copy_error (ctx);"
+ << endl
+ << "if (ctx.error_type ())" << endl
+ << "return;"
+ << endl;
+ }
+
+ // Only a globally-defined element can be a subst-group root.
+ //
+ if (poly && e.global ())
+ {
+ if (e.qualified () && e.namespace_ ().name ())
+ os << "const char* ns = " <<
+ strlit (e.namespace_ ().name ()) << ";";
+ else
+ os << "const char* ns = 0;";
+
+ os << "const char* n = " << strlit (e.name ()) << ";"
+ << endl;
+
+ os << "if (dt != 0 && " <<
+ "::xsde::cxx::serializer::substitution_map_instance ()" <<
+ ".check (ns, n, dt))" << endl
+ << "dt = 0;"
+ << endl;
+
+ if (exceptions)
+ {
+ os << "if (ns != 0)" << endl
+ << "this->_start_element (ns, n);"
+ << "else" << endl
+ << "this->_start_element (n);"
+ << endl;
+ }
+ else
+ {
+ os << "if (ns != 0)"
+ << "{"
+ << "if (!this->_start_element (ns, n))" << endl
+ << "return;"
+ << "}"
+ << "else"
+ << "{"
+ << "if (!this->_start_element (n))" << endl
+ << "return;"
+ << "}";
+ }
+ }
+ else
+ {
+ if (exceptions)
+ {
+ if (e.qualified () && e.namespace_ ().name ())
+ os << "this->_start_element (" <<
+ strlit (e.namespace_ ().name ()) << ", " <<
+ strlit (e.name ()) << ");";
+ else
+ os << "this->_start_element (" << strlit (e.name ()) << ");";
+ }
+ else
+ {
+ os << "if (!";
+
+ if (e.qualified () && e.namespace_ ().name ())
+ os << "this->_start_element (" <<
+ strlit (e.namespace_ ().name ()) << ", " <<
+ strlit (e.name ()) << ")";
+ else
+ os << "this->_start_element (" << strlit (e.name ()) << ")";
+
+ os << ")" << endl
+ << "return;"
+ << endl;
+ }
+ }
+
+ if (poly)
+ {
+ // Set xsi:type if necessary.
+ //
+ if (exceptions)
+ os << "if (dt != 0)" << endl
+ << "this->_set_type (dt);"
+ << endl;
+ else
+ os << "if (dt != 0)"
+ << "{"
+ << "if (!this->_set_type (dt))" << endl
+ << "return;"
+ << "}";
+ }
+
+ os << inst << "->_pre_impl (ctx);";
+
+ os << endl
+ << "if (ctx.error_type ())" << endl
+ << "return;"
+ << endl;
+
+ os << inst << "->_serialize_attributes ();";
+
+ os << endl
+ << "if (ctx.error_type ())" << endl
+ << "return;"
+ << endl;
+
+ os << inst << "->_serialize_content ();";
+
+ os << endl
+ << "if (ctx.error_type ())" << endl
+ << "return;"
+ << endl;
+
+ os << inst << "->_post_impl ();";
+
+ os << endl
+ << "if (ctx.error_type ())" << endl
+ << "return;"
+ << endl;
+
+ if (exceptions)
+ os << "this->_end_element ();";
+ else
+ os << "if (!this->_end_element ())" << endl
+ << "return;"
+ << endl;
+
+ os << inst << "->post ();";
+
+ if (!exceptions)
+ {
+ // Note that after post() we need to check both parser and
+ // context error states because of the recursive parsing.
+ //
+ os << endl
+ << "if (" << inst << "->_error_type ())" << endl
+ << inst << "->_copy_error (ctx);"
+ << endl
+ << "if (ctx.error_type ())" << endl
+ << "return;";
+ }
+
+ os << "}"; // if (inst)
+
+ if (min != 0)
+ {
+ os << "else"
+ << "{"
+ << "this->_schema_error (" <<
+ "::xsde::cxx::schema_error::expected_element);"
+ << "return;"
+ << "}";
+ }
+
+ os << "}";
+
+ if (min == 0 && max == 1)
+ {
+ if (!exceptions)
+ os << "if (ctx.error_type ())" << endl
+ << "return;"
+ << endl;
+ }
+ else if (max != 1)
+ {
+ if (!exceptions)
+ os << "if (ctx.error_type ())" << endl
+ << "return;"
+ << endl;
+
+ if (max != 0 || min != 0)
+ {
+ if (min != 0)
+ {
+ os << "if (i < " << min << "UL)"
+ << "{"
+ << "this->_schema_error (" <<
+ "::xsde::cxx::schema_error::expected_element);"
+ << "return;"
+ << "}";
+ }
+
+ os << "}";
+ }
+ }
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Any& a)
+ {
+ UnsignedLong min (a.min ()), max (a.max ());
+
+ if (min == 0 && max == 1)
+ {
+ os << "if (this->" << epresent (a) << " ())";
+
+ }
+ else if (max != 1)
+ {
+ // We only need to count if max != unbounded || min != 0.
+ //
+ if (max != 0 || min != 0)
+ {
+ os << "{"
+ << "size_t i = 0;"
+ << "for (; ";
+
+ if (max != 0)
+ os << "i < " << max << "UL && ";
+
+ os << "this->" << enext (a) << " (); ++i)";
+ }
+ else
+ os << "while (this->" << enext (a) << " ())";
+ }
+
+ os << "{";
+
+ if (stl)
+ {
+ os << "::std::string ns, name;"
+ << "this->" << ename (a) << " (ns, name);"
+ << endl;
+
+ if (!exceptions)
+ os << "if (ctx.error_type ())" << endl
+ << "return;"
+ << endl;
+
+ os << "if (";
+
+ any_test_.dispatch (a);
+
+ os << ")"
+ << "{";
+
+ os << "if (ns.empty ())"
+ << "{";
+
+ if (exceptions)
+ os << "this->_start_element (name.c_str ());";
+ else
+ os << "if (!this->_start_element (name.c_str ()))" << endl
+ << "return;";
+
+ os << "}"
+ << "else"
+ << "{";
+
+ if (exceptions)
+ os << "this->_start_element (ns.c_str (), name.c_str ());";
+ else
+ os << "if (!this->_start_element (ns.c_str (), " <<
+ "name.c_str ()))" << endl
+ << "return;";
+
+ os << "}"
+ << "this->" << eserialize (a) << " ();"
+ << endl
+ << "if (ctx.error_type ())" << endl
+ << "return;"
+ << endl;
+
+ if (exceptions)
+ os << "this->_end_element ();";
+ else
+ os << "if (!this->_end_element ())" << endl
+ << "return;";
+
+ os << "}" // test
+ << "else"
+ << "{"
+ << "this->_schema_error (" <<
+ "::xsde::cxx::schema_error::unexpected_element);"
+ << "return;"
+ << "}";
+ }
+ else
+ {
+ os << "const char* ns = 0;"
+ << "const char* name;"
+ << "bool free;"
+ << "this->" << ename (a) << " (ns, name, free);"
+ << endl;
+
+ if (!exceptions)
+ os << "if (ctx.error_type ())" << endl
+ << "return;"
+ << endl;
+ else
+ os << "::xsde::cxx::string auto_ns, auto_name;"
+ << "if (free)"
+ << "{"
+ << "auto_ns.attach (const_cast< char* > (ns));"
+ << "auto_name.attach (const_cast< char* > (name));"
+ << "}";
+
+ os << "if (";
+
+ any_test_.dispatch (a);
+
+ os << ")"
+ << "{";
+
+ if (exceptions)
+ os << "if (ns == 0 || *ns == '\\0')" << endl
+ << "this->_start_element (name);"
+ << "else" << endl
+ << "this->_start_element (ns, name);"
+ << endl;
+ else
+ os << "bool r;"
+ << "if (ns == 0 || *ns == '\\0')" << endl
+ << "r = this->_start_element (name);"
+ << "else" << endl
+ << "r = this->_start_element (ns, name);"
+ << endl
+ << "if (free)"
+ << "{"
+ << "delete[] ns;"
+ << "delete[] name;"
+ << "}"
+ << "if (!r)" << endl
+ << "return;"
+ << endl;
+
+ os << "this->" << eserialize (a) << " ();"
+ << endl
+ << "if (ctx.error_type ())" << endl
+ << "return;"
+ << endl;
+
+ if (exceptions)
+ os << "this->_end_element ();";
+ else
+ os << "if (!this->_end_element ())" << endl
+ << "return;";
+
+ os << "}" // test
+ << "else"
+ << "{"
+ << "this->_schema_error (" <<
+ "::xsde::cxx::schema_error::unexpected_element);"
+ << "return;"
+ << "}";
+ }
+
+ os << "}";
+
+ if (min == 0 && max == 1)
+ {
+ if (!exceptions)
+ os << "if (ctx.error_type ())" << endl
+ << "return;"
+ << endl;
+ }
+ else if (max != 1)
+ {
+ if (!exceptions)
+ os << "if (ctx.error_type ())" << endl
+ << "return;"
+ << endl;
+
+ if (max != 0 || min != 0)
+ {
+ if (min != 0)
+ {
+ os << "if (i < " << min << "UL)"
+ << "{"
+ << "this->_schema_error (" <<
+ "::xsde::cxx::schema_error::expected_element);"
+ << "return;"
+ << "}";
+ }
+
+ os << "}";
+ }
+ }
+ }
+
+ private:
+ AnyTest any_test_;
+ };
+
+ //
+ //
+ struct Complex : Traversal::Complex, Context
+ {
+ Complex (Context& c)
+ : Context (c),
+ compositor_ (c),
+ particle_ (c)
+ {
+ contains_compositor_ >> compositor_;
+ compositor_ >> contains_particle_;
+ contains_particle_ >> compositor_;
+ contains_particle_ >> particle_;
+ }
+
+ virtual Void
+ traverse (Type& c)
+ {
+ if (!has<Traversal::Element> (c) &&
+ !has_particle<Traversal::Any> (c))
+ return;
+
+ // Don't use restriction_p here since we don't want special
+ // treatment of anyType.
+ //
+ Boolean restriction (
+ c.inherits_p () &&
+ c.inherits ().is_a<SemanticGraph::Restricts> ());
+
+ String const& name (ename (c));
+
+ os <<"// Element validation and serialization for " <<
+ name << "." << endl
+ <<"//" << endl;
+
+ os << "void " << name << "::" << endl
+ << "_serialize_content ()"
+ << "{"
+ << "::xsde::cxx::serializer::context& ctx = this->_context ();"
+ << endl;
+
+ if (c.inherits_p () && !restriction)
+ {
+ // We cannot use the fully-qualified base name directly
+ // because of some broken compilers (EVC 4.0).
+ //
+ String base (unclash (name, "base"));
+
+ os << "typedef " << fq_name (c.inherits ().base ()) << " " <<
+ base << ";"
+ << base << "::_serialize_content ();"
+ << endl
+ << "if (ctx.error_type ())" << endl
+ << "return;"
+ << endl;
+ }
+
+ contains_compositor (c, contains_compositor_);
+
+ os << "}";
+ }
+
+ private:
+ Compositor compositor_;
+ Particle particle_;
+ Traversal::ContainsCompositor contains_compositor_;
+ Traversal::ContainsParticle contains_particle_;
+ };
+ }
+
+ Void
+ generate_element_validation_source (Context& ctx)
+ {
+ Traversal::Schema schema;
+
+ Traversal::Sources sources;
+ Traversal::Names schema_names;
+
+ Namespace ns (ctx);
+ Traversal::Names names;
+
+ schema >> sources >> schema;
+ schema >> schema_names >> ns >> names;
+
+ Complex complex (ctx);
+
+ names >> complex;
+
+ schema.dispatch (ctx.schema_root);
+ }
+ }
+}
diff --git a/xsde/cxx/serializer/element-validation-source.hxx b/xsde/cxx/serializer/element-validation-source.hxx
new file mode 100644
index 0000000..5649457
--- /dev/null
+++ b/xsde/cxx/serializer/element-validation-source.hxx
@@ -0,0 +1,22 @@
+// file : xsde/cxx/serializer/element-validation-source.hxx
+// author : Boris Kolpackov <boris@codesynthesis.com>
+// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC
+// license : GNU GPL v2 + exceptions; see accompanying LICENSE file
+
+#ifndef CXX_SERIALIZER_ELEMENT_VALIDATION_SOURCE_HXX
+#define CXX_SERIALIZER_ELEMENT_VALIDATION_SOURCE_HXX
+
+#include <xsd-frontend/semantic-graph/schema.hxx>
+
+#include <cxx/serializer/elements.hxx>
+
+namespace CXX
+{
+ namespace Serializer
+ {
+ Void
+ generate_element_validation_source (Context&);
+ }
+}
+
+#endif // CXX_SERIALIZER_ELEMENT_VALIDATION_SOURCE_HXX
diff --git a/xsde/cxx/serializer/elements.cxx b/xsde/cxx/serializer/elements.cxx
new file mode 100644
index 0000000..f130254
--- /dev/null
+++ b/xsde/cxx/serializer/elements.cxx
@@ -0,0 +1,278 @@
+// file : xsde/cxx/serializer/elements.cxx
+// author : Boris Kolpackov <boris@codesynthesis.com>
+// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC
+// license : GNU GPL v2 + exceptions; see accompanying LICENSE file
+
+#include <cxx/serializer/elements.hxx>
+
+namespace CXX
+{
+ namespace Serializer
+ {
+ Context::
+ Context (std::wostream& o,
+ SemanticGraph::Schema& root,
+ CLI::Options const& ops,
+ Regex const* he,
+ Regex const* ie,
+ Regex const* hie)
+ : CXX::Context (o,
+ root,
+ "s:name",
+ "char",
+ ops.value<CLI::include_with_brackets> (),
+ ops.value<CLI::include_prefix> (),
+ "", // export symbol
+ ops.value<CLI::namespace_map> (),
+ ops.value<CLI::namespace_regex> (),
+ ops.value<CLI::namespace_regex_trace> (),
+ ops.value<CLI::include_regex> (),
+ ops.value<CLI::include_regex_trace> (),
+ ops.value<CLI::generate_inline> (),
+ ops.value<CLI::reserved_name> ()),
+ options (ops),
+ xml_serializer (xml_serializer_),
+ serializer_base (serializer_base_),
+ simple_base (simple_base_),
+ complex_base (complex_base_),
+ serializer_map (serializer_map_),
+ validation (!ops.value<CLI::suppress_validation> ()),
+ exceptions (!ops.value<CLI::no_exceptions> ()),
+ stl (!ops.value<CLI::no_stl> ()),
+ poly_code (ops.value<CLI::generate_polymorphic> ()),
+ poly_runtime (poly_code || ops.value<CLI::runtime_polymorphic> ()),
+ reset (!ops.value<CLI::suppress_reset> ()),
+ mixin (ops.value<CLI::reuse_style_mixin> ()),
+ tiein (!mixin && !ops.value<CLI::reuse_style_none> ()),
+ hxx_expr (he),
+ ixx_expr (ie),
+ hxx_impl_expr (hie),
+ xml_serializer_ ("genx")
+ {
+ String xs_ns (xs_ns_name ());
+
+ string_type = L"::xsde::cxx::ro_string";
+
+ serializer_base_ = xs_ns + L"::serializer_base";
+
+ simple_base_ = L"::xsde::cxx::serializer::";
+ simple_base_ += (validation ? L"validating" : L"non_validating");
+ simple_base_ += L"::simple_content";
+
+ complex_base_ = L"::xsde::cxx::serializer::";
+ complex_base_ += (validation ? L"validating" : L"non_validating");
+ complex_base_ += L"::complex_content";
+
+ if (poly_code)
+ serializer_map_ = xs_ns + L"::serializer_map";
+ }
+
+ String Context::
+ real_fq_name (SemanticGraph::Nameable& n)
+ {
+ SemanticGraph::Context& c (n.context ());
+
+ if (c.count ("s:real-name"))
+ return c.get<String> ("s:real-name");
+ else
+ return fq_name (n);
+ }
+
+ Content::Value Context::
+ content (SemanticGraph::Complex& c)
+ {
+ using namespace SemanticGraph;
+
+ if (c.mixed ())
+ return Content::mixed;
+
+ if (c.inherits_p ())
+ {
+ Type& base (c.inherits ().base ());
+
+ if (Complex* cb = dynamic_cast<Complex*> (&base))
+ return content (*cb);
+
+ if (base.is_a<AnyType> ())
+ return Content::complex;
+
+ // Everyhting else (built-in type and AnySimpleType) is simple
+ // content.
+ //
+ return Content::simple;
+ }
+ else
+ return Content::complex;
+ }
+
+ String const& Context::
+ ret_type (SemanticGraph::Type& t)
+ {
+ return t.context ().get<String> ("s:ret-type");
+ }
+
+ String const& Context::
+ arg_type (SemanticGraph::Type& t)
+ {
+ return t.context ().get<String> ("s:arg-type");
+ }
+
+ //
+ //
+ String const& Context::
+ epresent (SemanticGraph::Particle& p)
+ {
+ return p.context ().get<String> ("s:present");
+ }
+
+ String const& Context::
+ epresent (SemanticGraph::Attribute& a)
+ {
+ return a.context ().get<String> ("s:present");
+ }
+
+ String const& Context::
+ enext (SemanticGraph::Particle& p)
+ {
+ return p.context ().get<String> ("s:next");
+ }
+
+ String const& Context::
+ enext (SemanticGraph::AnyAttribute& a)
+ {
+ return a.context ().get<String> ("s:next");
+ }
+
+ String const& Context::
+ etag (SemanticGraph::Particle& p)
+ {
+ return p.context ().get<String> ("s:tag");
+ }
+
+ String const& Context::
+ earm (SemanticGraph::Choice& c)
+ {
+ return c.context ().get<String> ("s:arm");
+ }
+
+ String const& Context::
+ earm_tag (SemanticGraph::Choice& c)
+ {
+ return c.context ().get<String> ("s:arm-tag");
+ }
+
+ //
+ //
+ String const& Context::
+ eserializer (SemanticGraph::Member& m)
+ {
+ return m.context ().get<String> ("s:serializer");
+ }
+
+ String const& Context::
+ emember (SemanticGraph::Member& m)
+ {
+ return m.context ().get<String> ("s:member");
+ }
+
+ String const& Context::
+ emember_map (SemanticGraph::Member& m)
+ {
+ return m.context ().get<String> ("s:member-map");
+ }
+
+ String const& Context::
+ etiein (SemanticGraph::Type& t)
+ {
+ return t.context ().get<String> ("s:tiein");
+ }
+
+ //
+ //
+ String const& Context::
+ eserialize (SemanticGraph::Any& a)
+ {
+ return a.context ().get<String> ("s:serialize");
+ }
+
+ String const& Context::
+ eserialize (SemanticGraph::AnyAttribute& a)
+ {
+ return a.context ().get<String> ("s:serialize");
+ }
+
+ //
+ //
+ String const& Context::
+ eimpl (SemanticGraph::Type& t)
+ {
+ return t.context ().get<String> ("s:impl");
+ }
+
+ // Includes
+ //
+ Void TypeForward::
+ traverse (SemanticGraph::Type& t)
+ {
+ os << "class " << t.context ().get<String> (name_key_) << ";";
+ }
+
+ Void Includes::
+ traverse_ (SemanticGraph::Uses& u)
+ {
+ // Support for weak (forward) inclusion used in the file-per-type
+ // compilation model.
+ //
+ Boolean weak (u.context ().count ("weak"));
+
+ if (weak && (type_ == header || type_ == impl_header))
+ {
+ // Generate forward declarations. We don't really need them
+ // in the impl files.
+ //
+ if (type_ == header)
+ schema_.dispatch (u.schema ());
+
+ return;
+ }
+
+ if (type_ == source && !weak)
+ return;
+
+ SemanticGraph::Path path (u.path ());
+
+ // Try to use the portable representation of the path. If that
+ // fails, fall back to the native representation.
+ //
+ NarrowString path_str;
+ try
+ {
+ path_str = path.string ();
+ }
+ catch (SemanticGraph::InvalidPath const&)
+ {
+ path_str = path.native_file_string ();
+ }
+
+ String inc_path;
+
+ switch (type_)
+ {
+ case header:
+ case source:
+ {
+ inc_path = ctx_.hxx_expr->merge (path_str);
+ break;
+ }
+ case impl_header:
+ {
+ inc_path = ctx_.hxx_impl_expr->merge (path_str);
+ break;
+ }
+ }
+
+ ctx_.os << "#include " << ctx_.process_include_path (inc_path) << endl
+ << endl;
+ }
+ }
+}
diff --git a/xsde/cxx/serializer/elements.hxx b/xsde/cxx/serializer/elements.hxx
new file mode 100644
index 0000000..c80ab5b
--- /dev/null
+++ b/xsde/cxx/serializer/elements.hxx
@@ -0,0 +1,443 @@
+// file : xsde/cxx/serializer/elements.hxx
+// author : Boris Kolpackov <boris@codesynthesis.com>
+// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC
+// license : GNU GPL v2 + exceptions; see accompanying LICENSE file
+
+#ifndef CXX_SERIALIZER_ELEMENTS_HXX
+#define CXX_SERIALIZER_ELEMENTS_HXX
+
+#include <sstream>
+
+#include <backend-elements/regex.hxx>
+
+#include <cxx/elements.hxx>
+
+#include <cxx/serializer/cli.hxx>
+
+namespace CXX
+{
+ namespace Serializer
+ {
+ struct Content
+ {
+ enum Value
+ {
+ simple,
+ complex,
+ mixed
+ };
+ };
+
+ //
+ //
+ class Context: public CXX::Context
+ {
+ public:
+ typedef BackendElements::Regex::Expression<Char> Regex;
+
+ public:
+ Context (std::wostream&,
+ SemanticGraph::Schema&,
+ CLI::Options const&,
+ Regex const* hxx_expr,
+ Regex const* ixx_expr,
+ Regex const* hxx_impl_expr);
+
+ protected:
+ Context (Context& c)
+ : CXX::Context (c),
+ options (c.options),
+ xml_serializer (c.xml_serializer),
+ serializer_base (c.serializer_base),
+ simple_base (c.simple_base),
+ complex_base (c.complex_base),
+ serializer_map (c.serializer_map),
+ validation (c.validation),
+ exceptions (c.exceptions),
+ stl (c.stl),
+ poly_code (c.poly_code),
+ poly_runtime (c.poly_runtime),
+ reset (c.reset),
+ mixin (c.mixin),
+ tiein (c.tiein),
+ hxx_expr (c.hxx_expr),
+ ixx_expr (c.ixx_expr),
+ hxx_impl_expr (c.hxx_impl_expr)
+ {
+ }
+
+ Context (Context& c, std::wostream& o)
+ : CXX::Context (c, o),
+ options (c.options),
+ xml_serializer (c.xml_serializer),
+ serializer_base (c.serializer_base),
+ simple_base (c.simple_base),
+ complex_base (c.complex_base),
+ serializer_map (c.serializer_map),
+ validation (c.validation),
+ exceptions (c.exceptions),
+ stl (c.stl),
+ poly_code (c.poly_code),
+ poly_runtime (c.poly_runtime),
+ reset (c.reset),
+ mixin (c.mixin),
+ tiein (c.tiein),
+ hxx_expr (c.hxx_expr),
+ ixx_expr (c.ixx_expr),
+ hxx_impl_expr (c.hxx_impl_expr)
+ {
+ }
+
+ public:
+ Boolean
+ restriction_p (SemanticGraph::Complex& c) const
+ {
+ if (c.inherits_p () &&
+ c.inherits ().is_a<SemanticGraph::Restricts> ())
+ {
+ // Restriction of anyType is a special case.
+ //
+ return !c.inherits ().base ().is_a<SemanticGraph::AnyType> ();
+ }
+
+ return false;
+ }
+
+ // Real (e.g., non-typedef) fq-name.
+ //
+ String
+ real_fq_name (SemanticGraph::Nameable& n);
+
+ public:
+ static Content::Value
+ content (SemanticGraph::Complex&);
+
+ public:
+ static String const&
+ ret_type (SemanticGraph::Type&);
+
+ static String const&
+ arg_type (SemanticGraph::Type&);
+
+ public:
+ // Optional.
+ //
+ static String const&
+ epresent (SemanticGraph::Particle&);
+
+ static String const&
+ epresent (SemanticGraph::Attribute&);
+
+ // Sequence.
+ //
+ static String const&
+ enext (SemanticGraph::Particle&);
+
+ static String const&
+ enext (SemanticGraph::AnyAttribute&);
+
+ // Choice.
+ //
+ static String const&
+ etag (SemanticGraph::Particle&);
+
+ static String const&
+ earm (SemanticGraph::Choice&);
+
+ static String const&
+ earm_tag (SemanticGraph::Choice&);
+
+ public:
+ static String const&
+ eserializer (SemanticGraph::Member&);
+
+ static String const&
+ emember (SemanticGraph::Member&);
+
+ static String const&
+ emember_map (SemanticGraph::Member&);
+
+ static String const&
+ etiein (SemanticGraph::Type&);
+
+ // serialize_*
+ //
+ public:
+ static String const&
+ eserialize (SemanticGraph::Any&);
+
+ static String const&
+ eserialize (SemanticGraph::AnyAttribute&);
+
+ public:
+ static String const&
+ eimpl (SemanticGraph::Type&);
+
+ public:
+ CLI::Options const& options;
+ String& xml_serializer;
+ String& serializer_base;
+ String& simple_base;
+ String& complex_base;
+ String& serializer_map;
+
+ Boolean validation;
+ Boolean exceptions;
+ Boolean stl;
+ Boolean poly_code;
+ Boolean poly_runtime;
+ Boolean reset;
+ Boolean mixin;
+ Boolean tiein;
+
+ Regex const* hxx_expr;
+ Regex const* ixx_expr;
+ Regex const* hxx_impl_expr;
+
+ private:
+ String xml_serializer_;
+ String serializer_base_;
+ String simple_base_;
+ String complex_base_;
+ String serializer_map_;
+ };
+
+ //
+ //
+ struct RequiredAttributeTest: Traversal::Attribute
+ {
+ RequiredAttributeTest (Boolean& result)
+ : result_ (result)
+ {
+ }
+
+ virtual Void
+ traverse (Type& a)
+ {
+ if (!result_ && !a.optional ())
+ result_ = true;
+ }
+
+ private:
+ Boolean& result_;
+ };
+
+
+ //
+ //
+ struct ParticleParamDecl: Traversal::Element, Context
+ {
+ ParticleParamDecl (Context& c, Boolean& first, Boolean name_arg)
+ : Context (c), first_ (first), name_arg_ (name_arg)
+ {
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Element& e)
+ {
+ if (!first_)
+ os << "," << endl;
+ else
+ first_ = false;
+
+ os << fq_name (e.type ()) << "&";
+
+ if (name_arg_)
+ os << " " << ename (e);
+ else
+ os << " /* " << comment (e.name ()) << " */";
+ }
+
+ private:
+ Boolean& first_;
+ Boolean name_arg_;
+ };
+
+ struct AttributeParamDecl: Traversal::Attribute, Context
+ {
+ AttributeParamDecl (Context& c, Boolean& first, Boolean name_arg)
+ : Context (c), first_ (first), name_arg_ (name_arg)
+ {
+ }
+
+ virtual Void
+ traverse (Type& a)
+ {
+ if (!first_)
+ os << "," << endl;
+ else
+ first_ = false;
+
+ os << fq_name (a.type ()) << "&";
+
+ if (name_arg_)
+ os << " " << ename (a);
+ else
+ os << " /* " << comment (a.name ()) << " */";
+ }
+
+ private:
+ Boolean& first_;
+ Boolean name_arg_;
+ };
+
+ struct SerializerParamDecl : Traversal::Complex,
+ Traversal::List,
+ Context
+ {
+ SerializerParamDecl (Context& c, Boolean name_arg)
+ : Context (c),
+ particle_ (c, first_, name_arg),
+ attribute_ (c, first_, name_arg),
+ first_ (true),
+ name_arg_ (name_arg)
+ {
+ inherits_ >> *this;
+
+ contains_compositor_ >> compositor_ >> contains_particle_;
+ contains_particle_ >> particle_;
+ contains_particle_ >> compositor_;
+
+ names_ >> attribute_;
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Complex& c)
+ {
+ inherits (c, inherits_);
+
+ if (!restriction_p (c))
+ {
+ names (c, names_);
+ contains_compositor (c, contains_compositor_);
+ }
+ }
+
+ virtual Void
+ traverse (SemanticGraph::List& l)
+ {
+ if (!first_)
+ os << "," << endl;
+ else
+ first_ = false;
+
+ os << fq_name (l.argumented ().type ()) << "&";
+
+ if (name_arg_)
+ os << " " << ename (l) << "_item";
+ else
+ os << " /* " << comment (l.name ()) << " item */";
+ }
+
+ private:
+ Traversal::Inherits inherits_;
+
+ Traversal::Compositor compositor_;
+ ParticleParamDecl particle_;
+ Traversal::ContainsCompositor contains_compositor_;
+ Traversal::ContainsParticle contains_particle_;
+
+ AttributeParamDecl attribute_;
+ Traversal::Names names_;
+
+ Boolean first_;
+ Boolean name_arg_;
+ };
+
+ //
+ //
+ struct TypeForward: Traversal::Type, Context
+ {
+ TypeForward (Context& c, Char const* name_key)
+ : Context (c), name_key_ (name_key)
+ {
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Type& t);
+
+ private:
+ Char const* name_key_;
+ };
+
+ struct Includes : Traversal::Imports,
+ Traversal::Includes
+ {
+ enum Type
+ {
+ header,
+ source,
+ impl_header
+ };
+
+ Includes (Context& c, Type t)
+ : ctx_ (c),
+ type_ (t),
+ namespace_ (c),
+ type_forward_ (c, t == header ? "s:name" : "s:impl")
+ {
+ schema_ >> schema_names_ >> namespace_ >> names_ >> type_forward_;
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Imports& i)
+ {
+ traverse_ (i);
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Includes& i)
+ {
+ traverse_ (i);
+ }
+
+ private:
+ Void
+ traverse_ (SemanticGraph::Uses&);
+
+ private:
+ Context& ctx_;
+ Type type_;
+
+ Traversal::Schema schema_;
+ Traversal::Names schema_names_;
+ Namespace namespace_;
+ Traversal::Names names_;
+ TypeForward type_forward_;
+ };
+
+ // Find root element for the test driver.
+ //
+ struct RootElement: Traversal::Element
+ {
+ RootElement (CLI::Options const& options,
+ SemanticGraph::Element*& element)
+ : options_ (options), element_ (element)
+ {
+ }
+
+ virtual Void
+ traverse (Type& e)
+ {
+ if (options_.value<CLI::root_element_first> ())
+ {
+ if (element_ == 0)
+ element_ = &e;
+ }
+ else if (String name = options_.value<CLI::root_element> ())
+ {
+ if (e.name () == name)
+ element_ = &e;
+ }
+ else
+ element_ = &e; // Cover root-element-last and no option.
+ }
+
+ private:
+ CLI::Options const& options_;
+ SemanticGraph::Element*& element_;
+ };
+ }
+}
+
+#endif // CXX_SERIALIZER_ELEMENTS_HXX
diff --git a/xsde/cxx/serializer/generator.cxx b/xsde/cxx/serializer/generator.cxx
new file mode 100644
index 0000000..c27ef09
--- /dev/null
+++ b/xsde/cxx/serializer/generator.cxx
@@ -0,0 +1,1600 @@
+// file : xsde/cxx/serializer/generator.cxx
+// author : Boris Kolpackov <boris@codesynthesis.com>
+// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC
+// license : GNU GPL v2 + exceptions; see accompanying LICENSE file
+
+#include <type-map/lexer.hxx>
+#include <type-map/parser.hxx>
+
+#include <cxx/serializer/elements.hxx>
+#include <cxx/serializer/generator.hxx>
+
+#include <cxx/serializer/validator.hxx>
+#include <cxx/serializer/name-processor.hxx>
+#include <cxx/serializer/type-processor.hxx>
+
+#include <cxx/serializer/serializer-forward.hxx>
+#include <cxx/serializer/serializer-header.hxx>
+#include <cxx/serializer/serializer-inline.hxx>
+#include <cxx/serializer/serializer-source.hxx>
+
+#include <cxx/serializer/impl-header.hxx>
+#include <cxx/serializer/impl-source.hxx>
+#include <cxx/serializer/driver-source.hxx>
+
+#include <cxx/serializer/element-validation-source.hxx>
+#include <cxx/serializer/attribute-validation-source.hxx>
+
+#include <xsd-frontend/semantic-graph.hxx>
+
+#include <backend-elements/regex.hxx>
+#include <backend-elements/indentation/cxx.hxx>
+#include <backend-elements/indentation/sloc.hxx>
+#include <backend-elements/indentation/clip.hxx>
+
+#include <cult/containers/set.hxx>
+#include <cult/containers/vector.hxx>
+
+#include <boost/filesystem/fstream.hpp>
+
+#include <iostream>
+
+#include <usage.hxx>
+
+#include "../../../libxsde/xsde/cxx/version.hxx"
+
+using std::endl;
+using std::wcerr;
+
+using namespace XSDFrontend::SemanticGraph;
+
+//
+//
+typedef
+boost::filesystem::wifstream
+WideInputFileStream;
+
+typedef
+boost::filesystem::wofstream
+WideOutputFileStream;
+
+typedef
+boost::filesystem::ifstream
+NarrowInputFileStream;
+
+namespace CXX
+{
+ namespace
+ {
+ Char const copyright_gpl[] =
+ "// Copyright (C) 2005-2009 Code Synthesis Tools CC\n"
+ "//\n"
+ "// This program was generated by CodeSynthesis XSD/e, an XML Schema\n"
+ "// to C++ data binding compiler for embedded systems.\n"
+ "//\n"
+ "// This program is free software; you can redistribute it and/or modify\n"
+ "// it under the terms of the GNU General Public License version 2 as\n"
+ "// published by the Free Software Foundation.\n"
+ "//\n"
+ "// This program is distributed in the hope that it will be useful,\n"
+ "// but WITHOUT ANY WARRANTY; without even the implied warranty of\n"
+ "// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n"
+ "// GNU General Public License for more details.\n"
+ "//\n"
+ "// You should have received a copy of the GNU General Public License\n"
+ "// along with this program; if not, write to the Free Software\n"
+ "// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA\n"
+ "//\n"
+ "//\n\n";
+
+ Char const copyright_proprietary[] =
+ "// Copyright (C) 2005-2009 Code Synthesis Tools CC\n"
+ "//\n"
+ "// This program was generated by CodeSynthesis XSD/e, an XML Schema to\n"
+ "// C++ data binding compiler for embedded systems, in the Proprietary\n"
+ "// License mode. You should have received a proprietary license from\n"
+ "// Code Synthesis Tools CC prior to generating this code. See the\n"
+ "// license text for conditions.\n"
+ "//\n\n";
+
+ Char const copyright_impl[] =
+ "// Not copyrighted - public domain.\n"
+ "//\n"
+ "// This sample serializer implementation was generated by CodeSynthesis XSD/e,\n"
+ "// an XML Schema to C++ data binding compiler for embedded systems. You may\n"
+ "// use it in your programs without any restrictions.\n"
+ "//\n\n";
+ }
+
+ namespace Serializer
+ {
+ namespace CLI
+ {
+ extern Key type_map = "type-map";
+ extern Key no_stl = "no-stl";
+ extern Key no_iostream = "no-iostream";
+ extern Key no_exceptions = "no-exceptions";
+ extern Key no_long_long = "no-long-long";
+ extern Key reuse_style_mixin = "reuse-style-mixin";
+ extern Key reuse_style_none = "reuse-style-none";
+ extern Key generate_inline = "generate-inline";
+ extern Key suppress_validation = "suppress-validation";
+ extern Key generate_polymorphic = "generate-polymorphic";
+ extern Key runtime_polymorphic = "runtime-polymorphic";
+ extern Key suppress_reset = "suppress-reset";
+ extern Key generate_empty_impl = "generate-empty-impl";
+ extern Key generate_test_driver = "generate-test-driver";
+ extern Key force_overwrite = "force-overwrite";
+ extern Key root_element_first = "root-element-first";
+ extern Key root_element_last = "root-element-last";
+ extern Key root_element = "root-element";
+ extern Key generate_xml_schema = "generate-xml-schema";
+ extern Key extern_xml_schema = "extern-xml-schema";
+ extern Key output_dir = "output-dir";
+ extern Key skel_type_suffix = "skel-type-suffix";
+ extern Key skel_file_suffix = "skel-file-suffix";
+ extern Key impl_type_suffix = "impl-type-suffix";
+ extern Key impl_file_suffix = "impl-file-suffix";
+ extern Key namespace_map = "namespace-map";
+ extern Key namespace_regex = "namespace-regex";
+ extern Key namespace_regex_trace = "namespace-regex-trace";
+ extern Key reserved_name = "reserved-name";
+ extern Key include_with_brackets = "include-with-brackets";
+ extern Key include_prefix = "include-prefix";
+ extern Key include_regex = "include-regex";
+ extern Key include_regex_trace = "include-regex-trace";
+ extern Key guard_prefix = "guard-prefix";
+ extern Key hxx_suffix = "hxx-suffix";
+ extern Key ixx_suffix = "ixx-suffix";
+ extern Key cxx_suffix = "cxx-suffix";
+ extern Key hxx_regex = "hxx-regex";
+ extern Key ixx_regex = "ixx-regex";
+ extern Key cxx_regex = "cxx-regex";
+ extern Key hxx_prologue = "hxx-prologue";
+ extern Key ixx_prologue = "ixx-prologue";
+ extern Key cxx_prologue = "cxx-prologue";
+ extern Key prologue = "prologue";
+ extern Key hxx_epilogue = "hxx-epilogue";
+ extern Key ixx_epilogue = "ixx-epilogue";
+ extern Key cxx_epilogue = "cxx-epilogue";
+ extern Key epilogue = "epilogue";
+ extern Key hxx_prologue_file = "hxx-prologue-file";
+ extern Key ixx_prologue_file = "ixx-prologue-file";
+ extern Key cxx_prologue_file = "cxx-prologue-file";
+ extern Key prologue_file = "prologue-file";
+ extern Key hxx_epilogue_file = "hxx-epilogue-file";
+ extern Key ixx_epilogue_file = "ixx-epilogue-file";
+ extern Key cxx_epilogue_file = "cxx-epilogue-file";
+ extern Key epilogue_file = "epilogue-file";
+ extern Key show_anonymous = "show-anonymous";
+ extern Key show_sloc = "show-sloc";
+ extern Key proprietary_license = "proprietary-license";
+ }
+ }
+
+ Void Serializer::Generator::
+ usage ()
+ {
+ std::wostream& e (wcerr);
+ ::CLI::Indent::Clip< ::CLI::OptionsUsage, WideChar> clip (e);
+
+ e << "--type-map <mapfile>" << endl
+ << " Read XML Schema to C++ type mapping information\n"
+ << " from <mapfile>. Repeat this option to specify\n"
+ << " several type maps. Type maps are considered in\n"
+ << " order of appearance and the first match is used."
+ << endl;
+
+ e << "--no-stl" << endl
+ << " Generate code that does not use STL."
+ << endl;
+
+ e << "--no-iostream" << endl
+ << " Generate code that does not use the iostream\n"
+ << " library."
+ << endl;
+
+ e << "--no-exceptions" << endl
+ << " Generate code that does not use C++ exceptions."
+ << endl;
+
+ e << "--no-long-long" << endl
+ << " Generate code that does not use the long long\n"
+ << " and unsigned long long types."
+ << endl;
+
+ e << "--reuse-style-mixin" << endl
+ << " Generate code that supports the mixin base\n"
+ << " serializer implementation reuse style."
+ << endl;
+
+ e << "--reuse-style-none" << endl
+ << " Do not generate any support for base serializer\n"
+ << " implementation reuse."
+ << endl;
+
+ e << "--generate-inline" << endl
+ << " Generate certain functions inline."
+ << endl;
+
+ e << "--suppress-validation" << endl
+ << " Suppress the generation of validation code."
+ << endl;
+
+ e << "--generate-polymorphic" << endl
+ << " Generate polymorphism-aware code. Specify this\n"
+ << " option if you use substitution groups or xsi:type."
+ << endl;
+
+ e << "--runtime-polymorphic" << endl
+ << " Generate non-polymorphic code that uses the\n"
+ << " runtime library configured with polymorphism\n"
+ << " support."
+ << endl;
+
+ e << "--suppress-reset" << endl
+ << " Suppress the generation of serializer reset code."
+ << endl;
+
+ e << "--generate-empty-impl" << endl
+ << " Generate a sample serializer implementation with\n"
+ << " empty function bodies."
+ << endl;
+
+ e << "--generate-test-driver" << endl
+ << " Generate a test driver for the sample serializer\n"
+ << " implementation."
+ << endl;
+
+ e << "--force-overwrite" << endl
+ << " Force overwriting of the existing implementation\n"
+ << " and test driver files."
+ << endl;
+
+ e << "--root-element-first" << endl
+ << " Indicate that the first global element is the\n"
+ << " document root."
+ << endl;
+
+ e << "--root-element-last" << endl
+ << " Indicate that the last global element is the\n"
+ << " document root."
+ << endl;
+
+ e << "--root-element <element>" << endl
+ << " Indicate that <element> is the document root."
+ << endl;
+
+ e << "--generate-xml-schema" << endl
+ << " Generate a C++ header file as if the schema being\n"
+ << " compiled defines the XML Schema namespace."
+ << endl;
+
+ e << "--extern-xml-schema <file>" << endl
+ << " Generate code as if the XML Schema namespace was\n"
+ << " defined in <file> and xsd:included in the schema\n"
+ << " being compiled."
+ << endl;
+
+ e << "--output-dir <dir>" << endl
+ << " Write generated files to <dir> instead of the\n"
+ << " current directory."
+ << endl;
+
+ e << "--skel-type-suffix <suffix>" << endl
+ << " Use <suffix> instead of the default '_sskel' to\n"
+ << " construct the names of generated serializer\n"
+ << " skeletons."
+ << endl;
+
+ e << "--skel-file-suffix <suffix>" << endl
+ << " Use <suffix> instead of the default '-sskel' to\n"
+ << " construct the names of generated serializer\n"
+ << " skeleton files."
+ << endl;
+
+ e << "--impl-type-suffix <suffix>" << endl
+ << " Use <suffix> instead of the default '_simpl' to\n"
+ << " construct the names of serializer implementations\n"
+ << " for the built-in XML Schema types and sample\n"
+ << " serializer implementations."
+ << endl;
+
+ e << "--impl-file-suffix <suffix>" << endl
+ << " Use <suffix> instead of the default '-simpl' to\n"
+ << " construct the names of generated sample\n"
+ << " serializer implementation files."
+ << endl;
+
+ e << "--namespace-map <xns>=<cns>" << endl
+ << " Map XML Schema namespace <xns> to C++ namespace\n"
+ << " <cns>. Repeat this option to specify mapping for\n"
+ << " more than one XML Schema namespace."
+ << endl;
+
+ e << "--namespace-regex <regex>" << endl
+ << " Add <regex> to the list of regular expressions\n"
+ << " used to translate XML Schema namespace names to\n"
+ << " C++ namespace names."
+ << endl;
+
+ e << "--namespace-regex-trace" << endl
+ << " Trace the process of applying regular expressions\n"
+ << " specified with the --namespace-regex option."
+ << endl;
+
+ e << "--reserved-name <name>" << endl
+ << " Add <name> to the list of names that should not\n"
+ << " be used as identifiers. The name can optionally\n"
+ << " be followed by '=' and the replacement name that\n"
+ << " should be used instead."
+ << endl;
+
+ e << "--include-with-brackets" << endl
+ << " Use angle brackets (<>) instead of quotes (\"\") in\n"
+ << " generated #include directives."
+ << endl;
+
+ e << "--include-prefix <prefix>" << endl
+ << " Add <prefix> to generated #include directive\n"
+ << " paths."
+ << endl;
+
+ e << "--include-regex <regex>" << endl
+ << " Add <regex> to the list of regular expressions\n"
+ << " used to transform #include directive paths."
+ << endl;
+
+ e << "--include-regex-trace" << endl
+ << " Trace the process of applying regular expressions\n"
+ << " specified with the --include-regex option."
+ << endl;
+
+ e << "--guard-prefix <prefix>" << endl
+ << " Add <prefix> to generated header inclusion guards."
+ << endl;
+
+ e << "--hxx-suffix <suffix>" << endl
+ << " Use <suffix> instead of the default '.hxx' to\n"
+ << " construct the name of the header file."
+ << endl;
+
+ e << "--ixx-suffix <suffix>" << endl
+ << " Use <suffix> instead of the default '.ixx' to\n"
+ << " construct the name of the inline file."
+ << endl;
+
+ e << "--cxx-suffix <suffix>" << endl
+ << " Use <suffix> instead of the default '.cxx' to\n"
+ << " construct the name of the source file."
+ << endl;
+
+ e << "--hxx-regex <regex>" << endl
+ << " Use <regex> to construct the name of the header\n"
+ << " file."
+ << endl;
+
+ e << "--ixx-regex <regex>" << endl
+ << " Use <regex> to construct the name of the inline\n"
+ << " file."
+ << endl;
+
+ e << "--cxx-regex <regex>" << endl
+ << " Use <regex> to construct the name of the source\n"
+ << " file."
+ << endl;
+
+
+ // Prologues.
+ //
+ e << "--hxx-prologue <text>" << endl
+ << " Insert <text> at the beginning of the header file."
+ << endl;
+
+ e << "--ixx-prologue <text>" << endl
+ << " Insert <text> at the beginning of the inline file."
+ << endl;
+
+ e << "--cxx-prologue <text>" << endl
+ << " Insert <text> at the beginning of the source file."
+ << endl;
+
+ e << "--prologue <text>" << endl
+ << " Insert <text> at the beginning of each generated\n"
+ << " file for which there is no file-specific prologue."
+ << endl;
+
+
+ // Epilogues.
+ //
+ e << "--hxx-epilogue <text>" << endl
+ << " Insert <text> at the end of the header file."
+ << endl;
+
+ e << "--ixx-epilogue <text>" << endl
+ << " Insert <text> at the end of the inline file."
+ << endl;
+
+ e << "--cxx-epilogue <text>" << endl
+ << " Insert <text> at the end of the source file."
+ << endl;
+
+ e << "--epilogue <text>" << endl
+ << " Insert <text> at the end of each generated file\n"
+ << " for which there is no file-specific epilogue."
+ << endl;
+
+
+ // Prologue files.
+ //
+ e << "--hxx-prologue-file <file>" << endl
+ << " Insert the content of the <file> at the beginning\n"
+ << " of the header file."
+ << endl;
+
+ e << "--ixx-prologue-file <file>" << endl
+ << " Insert the content of the <file> at the beginning\n"
+ << " of the inline file."
+ << endl;
+
+ e << "--cxx-prologue-file <file>" << endl
+ << " Insert the content of the <file> at the beginning\n"
+ << " of the source file."
+ << endl;
+
+ e << "--prologue-file <file>" << endl
+ << " Insert the content of the <file> at the beginning\n"
+ << " of each generated file for which there is no file-\n"
+ << " specific prologue file."
+ << endl;
+
+
+ // Epilogue files.
+ //
+ e << "--hxx-epilogue-file <file>" << endl
+ << " Insert the content of the <file> at the end of\n"
+ << " the header file."
+ << endl;
+
+ e << "--ixx-epilogue-file <file>" << endl
+ << " Insert the content of the <file> at the end of\n"
+ << " the inline file."
+ << endl;
+
+ e << "--cxx-epilogue-file <file>" << endl
+ << " Insert the content of the <file> at the end of\n"
+ << " the source file."
+ << endl;
+
+ e << "--epilogue-file <file>" << endl
+ << " Insert the content of the <file> at the end of\n"
+ << " each generated file for which there is no file-\n"
+ << " specific epilogue file."
+ << endl;
+
+
+ // Misc.
+ //
+ e << "--show-anonymous" << endl
+ << " Show elements and attributes that are of anonymous\n"
+ << " types."
+ << endl;
+
+ e << "--show-sloc" << endl
+ << " Show the number of generated physical source lines\n"
+ << " of code (SLOC)."
+ << endl;
+
+ e << "--sloc-limit <num>" << endl
+ << " Check that the number of generated physical source\n"
+ << " lines of code (SLOC) does not exceed <num>."
+ << endl;
+
+ e << "--options-file <file>" << endl
+ << " Read additional options from <file>. Each option\n"
+ << " should appear on a separate line optionally\n"
+ << " followed by space and an argument."
+ << endl;
+
+ e << "--proprietary-license" << endl
+ << " Indicate that the generated code is licensed under\n"
+ << " a proprietary license instead of the GPL."
+ << endl;
+ }
+
+ Serializer::CLI::OptionsSpec Serializer::Generator::
+ options_spec ()
+ {
+ CLI::OptionsSpec spec;
+
+ spec.option<CLI::skel_file_suffix> ().default_value ("-sskel");
+ spec.option<CLI::skel_type_suffix> ().default_value ("_sskel");
+ spec.option<CLI::impl_file_suffix> ().default_value ("-simpl");
+ spec.option<CLI::impl_type_suffix> ().default_value ("_simpl");
+
+ spec.option<CLI::hxx_suffix> ().default_value (".hxx");
+ spec.option<CLI::ixx_suffix> ().default_value (".ixx");
+ spec.option<CLI::cxx_suffix> ().default_value (".cxx");
+
+ return spec;
+ }
+
+
+ namespace
+ {
+ template <typename S>
+ Void
+ open (S& ifs, NarrowString const& path)
+ {
+ try
+ {
+ Path fs_path (path, boost::filesystem::native);
+ ifs.open (fs_path, std::ios_base::in | std::ios_base::binary);
+
+ if (!ifs.is_open ())
+ {
+ wcerr << path.c_str () << ": error: unable to open in read mode"
+ << endl;
+
+ throw Serializer::Generator::Failed ();
+ }
+ }
+ catch (InvalidPath const&)
+ {
+ wcerr << "error: '" << path.c_str () << "' is not a valid "
+ << "filesystem path" << endl;
+
+ throw Serializer::Generator::Failed ();
+ }
+ }
+
+ Void
+ append (WideOutputFileStream& os,
+ NarrowString const& path,
+ WideInputFileStream& default_is)
+ {
+ using std::ios_base;
+
+ if (path)
+ {
+ WideInputFileStream is;
+ open (is, path);
+ os << is.rdbuf ();
+ }
+ else if (default_is.is_open ())
+ {
+ os << default_is.rdbuf ();
+ default_is.seekg (0, ios_base::beg);
+ }
+ }
+
+ Void
+ append (WideOutputFileStream& os,
+ Cult::Containers::Vector<NarrowString> const& primary,
+ Cult::Containers::Vector<NarrowString> const& def)
+ {
+ Cult::Containers::Vector<NarrowString> const& v (
+ primary.empty () ? def : primary);
+
+ for (Containers::Vector<NarrowString>::ConstIterator
+ i (v.begin ()), e (v.end ()); i != e; ++i)
+ {
+ os << i->c_str () << endl;
+ }
+ }
+ }
+
+
+ UnsignedLong Serializer::Generator::
+ generate (Serializer::CLI::Options const& ops,
+ Schema& schema,
+ Path const& file_path,
+ TypeMap::Namespaces& type_map,
+ Boolean gen_driver,
+ const WarningSet& disabled_warnings,
+ FileList& file_list,
+ AutoUnlinks& unlinks)
+ {
+ using std::ios_base;
+ namespace Indentation = BackendElements::Indentation;
+
+ typedef BackendElements::Regex::Expression<Char> Regex;
+
+ try
+ {
+ Boolean generate_xml_schema (ops.value<CLI::generate_xml_schema> ());
+
+ // We could be compiling several schemas at once in which case
+ // handling of the --generate-xml-schema option gets tricky: we
+ // will need to rely on the presence of the --extern-xml-schema
+ // to tell us which (fake) schema file corresponds to XML Schema.
+ //
+ if (generate_xml_schema)
+ {
+ if (NarrowString name = ops.value<CLI::extern_xml_schema> ())
+ {
+ if (file_path.native_file_string () != name)
+ generate_xml_schema = false;
+ }
+ }
+
+ Boolean impl (!generate_xml_schema &&
+ ops.value<CLI::generate_empty_impl> ());
+
+ Boolean driver (gen_driver && !generate_xml_schema &&
+ ops.value<CLI::generate_test_driver> ());
+
+ // Evaluate the graph for possibility of generating something useful.
+ //
+ {
+ Validator validator;
+ if (!validator.validate (
+ ops, schema, file_path, driver, disabled_warnings))
+ throw Failed ();
+ }
+
+ // Process names.
+ //
+ {
+ NameProcessor proc;
+ proc.process (ops, schema, file_path);
+ }
+
+ //
+ //
+ Boolean validation (!ops.value<CLI::suppress_validation> ());
+
+ // Read-in type maps.
+ //
+ {
+ using namespace TypeMap;
+ typedef Containers::Vector<NarrowString> Files;
+
+ Files const& files (ops.value<CLI::type_map> ());
+
+ for (Files::ConstIterator f (files.begin ()); f != files.end (); ++f )
+ {
+ NarrowInputFileStream ifs;
+ open (ifs, *f);
+
+ Lexer l (ifs, *f);
+ TypeMap::Parser p (l, *f);
+
+ if (!p.parse (type_map))
+ throw Failed ();
+ }
+
+ // Add the built-in mappings at the end.
+ //
+ String xns;
+ {
+ Context ctx (std::wcerr, schema, ops, 0, 0, 0);
+ xns = ctx.xs_ns_name ();
+ }
+
+ if (ops.value<CLI::no_stl> ())
+ {
+ TypeMap::Namespace xsd_std ("http://www\\.w3\\.org/2001/XMLSchema");
+
+ String qname (L"const " + xns + L"::qname*");
+ String string_seq (L"const " + xns + L"::string_sequence*");
+
+ xsd_std.types_push_back ("string", "const char*", "const char*");
+ xsd_std.types_push_back ("normalizedString", "const char*", "const char*");
+ xsd_std.types_push_back ("token", "const char*", "const char*");
+ xsd_std.types_push_back ("Name", "const char*", "const char*");
+ xsd_std.types_push_back ("NMTOKEN", "const char*", "const char*");
+ xsd_std.types_push_back ("NMTOKENS", string_seq, string_seq);
+ xsd_std.types_push_back ("NCName", "const char*", "const char*");
+
+ xsd_std.types_push_back ("ID", "const char*", "const char*");
+ xsd_std.types_push_back ("IDREF", "const char*", "const char*");
+ xsd_std.types_push_back ("IDREFS", string_seq, string_seq);
+
+ xsd_std.types_push_back ("language", "const char*", "const char*");
+ xsd_std.types_push_back ("anyURI", "const char*", "const char*");
+ xsd_std.types_push_back ("QName", qname, qname);
+
+ type_map.push_back (xsd_std);
+ }
+ else
+ {
+ TypeMap::Namespace xsd_std ("http://www\\.w3\\.org/2001/XMLSchema");
+
+ String qname (xns + L"::qname");
+ String string_seq (L"const " + xns + L"::string_sequence*");
+
+ xsd_std.types_push_back ("string", "::std::string");
+ xsd_std.types_push_back ("normalizedString", "::std::string");
+ xsd_std.types_push_back ("token", "::std::string");
+ xsd_std.types_push_back ("Name", "::std::string");
+ xsd_std.types_push_back ("NMTOKEN", "::std::string");
+ xsd_std.types_push_back ("NMTOKENS", string_seq, string_seq);
+ xsd_std.types_push_back ("NCName", "::std::string");
+
+ xsd_std.types_push_back ("ID", "::std::string");
+ xsd_std.types_push_back ("IDREF", "::std::string");
+ xsd_std.types_push_back ("IDREFS", string_seq, string_seq);
+
+ xsd_std.types_push_back ("language", "::std::string");
+ xsd_std.types_push_back ("anyURI", "::std::string");
+ xsd_std.types_push_back ("QName", qname);
+
+ type_map.push_back (xsd_std);
+ }
+
+ String buffer (L"const " + xns + L"::buffer*");
+
+ TypeMap::Namespace xsd ("http://www\\.w3\\.org/2001/XMLSchema");
+
+ xsd.types_push_back ("boolean", "bool", "bool");
+
+ xsd.types_push_back ("byte", "signed char", "signed char");
+ xsd.types_push_back ("unsignedByte", "unsigned char", "unsigned char");
+
+ xsd.types_push_back ("short", "short", "short");
+ xsd.types_push_back ("unsignedShort", "unsigned short", "unsigned short");
+
+ xsd.types_push_back ("int", "int", "int");
+ xsd.types_push_back ("unsignedInt", "unsigned int", "unsigned int");
+
+ if (ops.value<CLI::no_long_long> ())
+ {
+ xsd.types_push_back ("long", "long", "long");
+ xsd.types_push_back ("unsignedLong", "unsigned long", "unsigned long");
+ }
+ else
+ {
+ xsd.types_push_back ("long", "long long", "long long");
+ xsd.types_push_back ("unsignedLong", "unsigned long long", "unsigned long long");
+ }
+
+ xsd.types_push_back ("integer", "long", "long");
+
+ xsd.types_push_back ("negativeInteger", "long", "long");
+ xsd.types_push_back ("nonPositiveInteger", "long", "long");
+
+ xsd.types_push_back ("positiveInteger", "unsigned long", "unsigned long");
+ xsd.types_push_back ("nonNegativeInteger", "unsigned long", "unsigned long");
+
+ xsd.types_push_back ("float", "float", "float");
+ xsd.types_push_back ("double", "double", "double");
+ xsd.types_push_back ("decimal", "double", "double");
+
+ xsd.types_push_back ("base64Binary", buffer, buffer);
+ xsd.types_push_back ("hexBinary", buffer, buffer);
+
+ xsd.types_push_back ("gDay", xns + L"::gday");
+ xsd.types_push_back ("gMonth", xns + L"::gmonth");
+ xsd.types_push_back ("gYear", xns + L"::gyear");
+ xsd.types_push_back ("gMonthDay", xns + L"::gmonth_day");
+ xsd.types_push_back ("gYearMonth", xns + L"::gyear_month");
+ xsd.types_push_back ("date", xns + L"::date");
+ xsd.types_push_back ("time", xns + L"::time");
+ xsd.types_push_back ("dateTime", xns + L"::date_time");
+ xsd.types_push_back ("duration", xns + L"::duration");
+
+ type_map.push_back (xsd);
+
+ // Everyhting else maps to void.
+ //
+ TypeMap::Namespace rest (".*");
+ rest.types_push_back (".*", "void", "void");
+ type_map.push_back (rest);
+ }
+
+ // Process types.
+ //
+ {
+ TypeProcessor proc;
+ proc.process (ops, schema, type_map);
+ }
+
+ // Generate code.
+ //
+ Boolean inline_ (ops.value<CLI::generate_inline> () &&
+ !generate_xml_schema);
+
+ Boolean source (!generate_xml_schema);
+
+ NarrowString name (file_path.leaf ());
+ NarrowString skel_suffix (ops.value <CLI::skel_file_suffix> ());
+ NarrowString impl_suffix (ops.value <CLI::impl_file_suffix> ());
+
+ NarrowString hxx_suffix (ops.value <CLI::hxx_suffix> ());
+ NarrowString ixx_suffix (ops.value <CLI::ixx_suffix> ());
+ NarrowString cxx_suffix (ops.value <CLI::cxx_suffix> ());
+
+
+ Regex hxx_expr (
+ ops.value <CLI::hxx_regex> ().empty ()
+ ? "#^(.+?)(\\.[^./\\\\]+)?$#$1" + skel_suffix + hxx_suffix + "#"
+ : ops.value <CLI::hxx_regex> ());
+
+ Regex ixx_expr (
+ ops.value <CLI::ixx_regex> ().empty ()
+ ? "#^(.+?)(\\.[^./\\\\]+)?$#$1" + skel_suffix + ixx_suffix + "#"
+ : ops.value <CLI::ixx_regex> ());
+
+ Regex cxx_expr (
+ ops.value <CLI::cxx_regex> ().empty ()
+ ? "#^(.+?)(\\.[^./\\\\]+)?$#$1" + skel_suffix + cxx_suffix + "#"
+ : ops.value <CLI::cxx_regex> ());
+
+ Regex hxx_impl_expr;
+ Regex cxx_impl_expr;
+ Regex cxx_driver_expr;
+
+ if (impl || driver)
+ {
+ hxx_impl_expr =
+ "#^(.+?)(\\.[^./\\\\]+)?$#$1" + impl_suffix + hxx_suffix + "#";
+
+ cxx_impl_expr =
+ "#^(.+?)(\\.[^./\\\\]+)?$#$1" + impl_suffix + cxx_suffix + "#";
+
+ cxx_driver_expr =
+ "#^(.+?)(\\.[^./\\\\]+)?$#$1-sdriver" + cxx_suffix + "#";
+ }
+
+ if (!hxx_expr.match (name))
+ {
+ wcerr << "error: header expression '" <<
+ hxx_expr.pattern () << "' does not match '" <<
+ name.c_str () << "'" << endl;
+ throw Failed ();
+ }
+
+ if (inline_ && !ixx_expr.match (name))
+ {
+ wcerr << "error: inline expression '" <<
+ ixx_expr.pattern () << "' does not match '" <<
+ name.c_str () << "'" << endl;
+ throw Failed ();
+ }
+
+ if (source && !cxx_expr.match (name))
+ {
+ wcerr << "error: source expression '" <<
+ cxx_expr.pattern () << "' does not match '" <<
+ name.c_str () << "'" << endl;
+ throw Failed ();
+ }
+
+ if (impl || driver)
+ {
+ if (!hxx_impl_expr.match (name))
+ {
+ wcerr << "error: implementation header expression '" <<
+ hxx_impl_expr.pattern () << "' does not match '" <<
+ name.c_str () << "'" << endl;
+ throw Failed ();
+ }
+
+ if (!cxx_impl_expr.match (name))
+ {
+ wcerr << "error: implementation source expression '" <<
+ cxx_impl_expr.pattern () << "' does not match '" <<
+ name.c_str () << "'" << endl;
+ throw Failed ();
+ }
+
+ if (!cxx_driver_expr.match (name))
+ {
+ wcerr << "error: driver source expression '" <<
+ cxx_driver_expr.pattern () << "' does not match '" <<
+ name.c_str () << "'" << endl;
+ throw Failed ();
+ }
+ }
+
+ NarrowString hxx_name (hxx_expr.merge (name));
+ NarrowString ixx_name (inline_ ? ixx_expr.merge (name) : NarrowString ());
+ NarrowString cxx_name (source ? cxx_expr.merge (name) : NarrowString ());
+
+ NarrowString hxx_impl_name;
+ NarrowString cxx_impl_name;
+ NarrowString cxx_driver_name;
+
+ if (impl || driver)
+ {
+ hxx_impl_name = hxx_impl_expr.merge (name);
+ cxx_impl_name = cxx_impl_expr.merge (name);
+ cxx_driver_name = cxx_driver_expr.merge (name);
+ }
+
+ Path hxx_path (hxx_name, boost::filesystem::native);
+ Path ixx_path (ixx_name, boost::filesystem::native);
+ Path cxx_path (cxx_name, boost::filesystem::native);
+
+ Path hxx_impl_path;
+ Path cxx_impl_path;
+ Path cxx_driver_path;
+
+ if (impl || driver)
+ {
+ hxx_impl_path = Path (hxx_impl_name, boost::filesystem::native);
+ cxx_impl_path = Path (cxx_impl_name, boost::filesystem::native);
+ cxx_driver_path = Path (cxx_driver_name, boost::filesystem::native);
+ }
+
+ if (NarrowString dir = ops.value<CLI::output_dir> ())
+ {
+ try
+ {
+ Path path (dir, boost::filesystem::native);
+
+ hxx_path = path / hxx_path;
+ ixx_path = path / ixx_path;
+ cxx_path = path / cxx_path;
+
+ if (impl || driver)
+ {
+ hxx_impl_path = path / hxx_impl_path;
+ cxx_impl_path = path / cxx_impl_path;
+ cxx_driver_path = path /cxx_driver_path;
+ }
+
+ }
+ catch (InvalidPath const&)
+ {
+ wcerr << dir.c_str () << ": error: invalid path" << endl;
+ throw Failed ();
+ }
+ }
+
+ // Open the impl files first so that if open fails, the skel files
+ // are not deleted.
+ //
+ WideOutputFileStream hxx_impl;
+ WideOutputFileStream cxx_impl;
+ WideOutputFileStream cxx_driver;
+
+ if (impl)
+ {
+ if (!ops.value<CLI::force_overwrite> ())
+ {
+ WideInputFileStream tmp (hxx_impl_path, ios_base::in);
+
+ if (tmp.is_open ())
+ {
+ wcerr << hxx_impl_path << ": error: cowardly refusing to " <<
+ "overwrite an existing file" << endl;
+ throw Failed ();
+ }
+
+ tmp.close ();
+ }
+
+ hxx_impl.open (hxx_impl_path, ios_base::out);
+
+ if (!hxx_impl.is_open ())
+ {
+ wcerr << hxx_impl_path << ": error: unable to open in write mode"
+ << endl;
+ throw Failed ();
+ }
+
+ unlinks.add (hxx_impl_path);
+ file_list.push_back (hxx_impl_path.native_file_string ());
+
+ if (!ops.value<CLI::force_overwrite> ())
+ {
+ WideInputFileStream tmp (cxx_impl_path, ios_base::in);
+
+ if (tmp.is_open ())
+ {
+ wcerr << cxx_impl_path << ": error: cowardly refusing to " <<
+ "overwrite an existing file" << endl;
+ throw Failed ();
+ }
+
+ tmp.close ();
+ }
+
+ cxx_impl.open (cxx_impl_path, ios_base::out);
+
+ if (!cxx_impl.is_open ())
+ {
+ wcerr << cxx_impl_path << ": error: unable to open in write mode"
+ << endl;
+ throw Failed ();
+ }
+
+ unlinks.add (cxx_impl_path);
+ file_list.push_back (cxx_impl_path.native_file_string ());
+ }
+
+ if (driver)
+ {
+ if (!ops.value<CLI::force_overwrite> ())
+ {
+ WideInputFileStream tmp (cxx_driver_path, ios_base::in);
+
+ if (tmp.is_open ())
+ {
+ wcerr << cxx_driver_path << ": error: cowardly refusing to " <<
+ "overwrite an existing file" << endl;
+ throw Failed ();
+ }
+
+ tmp.close ();
+ }
+
+ cxx_driver.open (cxx_driver_path, ios_base::out);
+
+ if (!cxx_driver.is_open ())
+ {
+ wcerr << cxx_driver_path << ": error: unable to open in write " <<
+ "mode" << endl;
+ throw Failed ();
+ }
+
+ unlinks.add (cxx_driver_path);
+ file_list.push_back (cxx_driver_path.native_file_string ());
+ }
+
+ // Open the skel files.
+ //
+ WideOutputFileStream hxx (hxx_path, ios_base::out);
+ WideOutputFileStream ixx;
+ WideOutputFileStream cxx;
+
+ if (!hxx.is_open ())
+ {
+ wcerr << hxx_path << ": error: unable to open in write mode" << endl;
+ throw Failed ();
+ }
+
+ unlinks.add (hxx_path);
+ file_list.push_back (hxx_path.native_file_string ());
+
+ if (inline_)
+ {
+ ixx.open (ixx_path, ios_base::out);
+
+ if (!ixx.is_open ())
+ {
+ wcerr << ixx_path << ": error: unable to open in write mode" << endl;
+ throw Failed ();
+ }
+
+ unlinks.add (ixx_path);
+ file_list.push_back (ixx_path.native_file_string ());
+ }
+
+ if (source)
+ {
+ cxx.open (cxx_path, ios_base::out);
+
+ if (!cxx.is_open ())
+ {
+ wcerr << cxx_path << ": error: unable to open in write mode" << endl;
+ throw Failed ();
+ }
+
+ unlinks.add (cxx_path);
+ file_list.push_back (cxx_path.native_file_string ());
+ }
+
+ // Print copyright and license.
+ //
+ Char const* copyright (
+ ops.value<CLI::proprietary_license> ()
+ ? copyright_proprietary
+ : copyright_gpl);
+
+ hxx << copyright;
+
+ if (inline_)
+ ixx << copyright;
+
+ if (source)
+ cxx << copyright;
+
+ if (impl)
+ {
+ hxx_impl << copyright_impl;
+ cxx_impl << copyright_impl;
+ }
+
+ if (driver)
+ cxx_driver << copyright_impl;
+
+ // Prologue.
+ //
+ WideInputFileStream prologue;
+ {
+ NarrowString name (ops.value<CLI::prologue_file> ());
+
+ if (name)
+ open (prologue, name);
+ }
+
+ // Epilogue.
+ //
+ WideInputFileStream epilogue;
+ {
+ NarrowString name (ops.value<CLI::epilogue_file> ());
+
+ if (name)
+ open (epilogue, name);
+ }
+
+
+ // SLOC counter.
+ //
+ UnsignedLong sloc (0);
+ Boolean show_sloc (ops.value<CLI::show_sloc> ());
+
+
+ //
+ //
+ Regex guard_expr ("/([a-z])([A-Z])/$1_$2/"); // Split words.
+
+ NarrowString guard_prefix (ops.value<CLI::guard_prefix> ());
+
+ if (!guard_prefix)
+ guard_prefix = file_path.branch_path ().native_directory_string ();
+
+ if (guard_prefix)
+ guard_prefix += '_';
+
+
+ // HXX
+ //
+ {
+ Context ctx (hxx, schema, ops, &hxx_expr, &ixx_expr, &hxx_impl_expr);
+
+ Indentation::Clip<Indentation::SLOC, WideChar> hxx_sloc (hxx);
+
+ String guard (guard_expr.merge (guard_prefix + hxx_name));
+ guard = ctx.escape (guard); // Make it a C++ id.
+ std::transform (guard.begin (), guard.end(), guard.begin (), upcase);
+
+ hxx << "#ifndef " << guard << endl
+ << "#define " << guard << endl
+ << endl;
+
+ // Copy prologue.
+ //
+ hxx << "// Begin prologue." << endl
+ << "//" << endl;
+
+ append (
+ hxx, ops.value<CLI::hxx_prologue> (), ops.value<CLI::prologue> ());
+ append (hxx, ops.value<CLI::hxx_prologue_file> (), prologue);
+
+ hxx << "//" << endl
+ << "// End prologue." << endl
+ << endl;
+
+ {
+ // Version check.
+ //
+ hxx << "#include <xsde/cxx/version.hxx>" << endl
+ << endl
+ << "#if (XSDE_INT_VERSION != " << XSDE_INT_VERSION << "L)" << endl
+ << "#error XSD/e runtime version mismatch" << endl
+ << "#endif" << endl
+ << endl;
+
+ // Runtime/generated code compatibility checks.
+ //
+
+ hxx << "#include <xsde/cxx/config.hxx>" << endl
+ << endl;
+
+ if (ops.value<CLI::no_stl> ())
+ {
+ hxx << "#ifdef XSDE_STL" << endl
+ << "#error the XSD/e runtime uses STL while the " <<
+ "generated code does not (reconfigure the runtime or " <<
+ "remove --no-stl)" << endl
+ << "#endif" << endl
+ << endl;
+ }
+ else
+ {
+ hxx << "#ifndef XSDE_STL" << endl
+ << "#error the generated code uses STL while the " <<
+ "XSD/e runtime does not (reconfigure the runtime or " <<
+ "add --no-stl)" << endl
+ << "#endif" << endl
+ << endl;
+ }
+
+ if (ops.value<CLI::no_iostream> ())
+ {
+ hxx << "#ifdef XSDE_IOSTREAM" << endl
+ << "#error the XSD/e runtime uses iostream while the " <<
+ "generated code does not (reconfigure the runtime or " <<
+ "remove --no-iostream)" << endl
+ << "#endif" << endl
+ << endl;
+ }
+ else
+ {
+ hxx << "#ifndef XSDE_IOSTREAM" << endl
+ << "#error the generated code uses iostream while the " <<
+ "XSD/e runtime does not (reconfigure the runtime or " <<
+ "add --no-iostream)" << endl
+ << "#endif" << endl
+ << endl;
+ }
+
+ if (ops.value<CLI::no_exceptions> ())
+ {
+ hxx << "#ifdef XSDE_EXCEPTIONS" << endl
+ << "#error the XSD/e runtime uses exceptions while the " <<
+ "generated code does not (reconfigure the runtime or " <<
+ "remove --no-exceptions)" << endl
+ << "#endif" << endl
+ << endl;
+ }
+ else
+ {
+ hxx << "#ifndef XSDE_EXCEPTIONS" << endl
+ << "#error the generated code uses exceptions while the " <<
+ "XSD/e runtime does not (reconfigure the runtime or " <<
+ "add --no-exceptions)" << endl
+ << "#endif" << endl
+ << endl;
+ }
+
+ if (ops.value<CLI::no_long_long> ())
+ {
+ hxx << "#ifdef XSDE_LONGLONG" << endl
+ << "#error the XSD/e runtime uses long long while the " <<
+ "generated code does not (reconfigure the runtime or " <<
+ "remove --no-long-long)" << endl
+ << "#endif" << endl
+ << endl;
+ }
+ else
+ {
+ hxx << "#ifndef XSDE_LONGLONG" << endl
+ << "#error the generated code uses long long while the " <<
+ "XSD/e runtime does not (reconfigure the runtime or " <<
+ "add --no-long-long)" << endl
+ << "#endif" << endl
+ << endl;
+ }
+
+ if (ops.value<CLI::suppress_validation> ())
+ {
+ hxx << "#ifdef XSDE_SERIALIZER_VALIDATION" << endl
+ << "#error the XSD/e runtime uses validation while the " <<
+ "generated code does not (reconfigure the runtime or " <<
+ "remove --suppress-validation)" << endl
+ << "#endif" << endl
+ << endl;
+ }
+ else
+ {
+ hxx << "#ifndef XSDE_SERIALIZER_VALIDATION" << endl
+ << "#error the generated code uses validation while the " <<
+ "XSD/e runtime does not (reconfigure the runtime or " <<
+ "add --suppress-validation)" << endl
+ << "#endif" << endl
+ << endl;
+ }
+
+ if (ops.value<CLI::generate_polymorphic> () ||
+ ops.value<CLI::runtime_polymorphic> ())
+ {
+ hxx << "#ifndef XSDE_POLYMORPHIC" << endl
+ << "#error the generated code expects XSD/e runtime with " <<
+ "polymorphism support (reconfigure the runtime or remove " <<
+ "--generate-polymorphic/--runtime-polymorphic)" << endl
+ << "#endif" << endl
+ << endl;
+ }
+ else
+ {
+ hxx << "#ifdef XSDE_POLYMORPHIC" << endl
+ << "#error the generated code expects XSD/e runtime " <<
+ "without polymorphism support (reconfigure the runtime or " <<
+ "add --generate-polymorphic/--runtime-polymorphic)" << endl
+ << "#endif" << endl
+ << endl;
+ }
+
+ if (ops.value<CLI::reuse_style_mixin> ())
+ {
+ hxx << "#ifndef XSDE_REUSE_STYLE_MIXIN" << endl
+ << "#error the generated code uses the mixin reuse style " <<
+ "while the XSD/e runtime does not (reconfigure the runtime " <<
+ "or remove --reuse-style-mixin)" << endl
+ << "#endif" << endl
+ << endl;
+ }
+ else if (ops.value<CLI::reuse_style_none> ())
+ {
+ hxx << "#ifndef XSDE_REUSE_STYLE_NONE" << endl
+ << "#error the generated code does not provide support " <<
+ "for serializer reuse while the XSD/e runtime does (" <<
+ "reconfigure the runtime or remove --reuse-style-none)" << endl
+ << "#endif" << endl
+ << endl;
+ }
+ else
+ {
+ hxx << "#ifndef XSDE_REUSE_STYLE_TIEIN" << endl
+ << "#error the generated code uses the tiein reuse style " <<
+ "while the XSD/e runtime does not (reconfigure the runtime " <<
+ "or add --reuse-style-mixin or --reuse-style-none)" << endl
+ << "#endif" << endl
+ << endl;
+ }
+
+ //
+ //
+
+ hxx << "#include <xsde/cxx/pre.hxx>" << endl
+ << endl;
+
+ // Set auto-indentation.
+ //
+ Indentation::Clip<Indentation::CXX, WideChar> hxx_clip (hxx);
+
+ // Generate.
+ //
+ if (!generate_xml_schema)
+ generate_serializer_forward (ctx);
+
+ generate_serializer_header (ctx, generate_xml_schema);
+
+
+ if (inline_)
+ hxx << "#include " << ctx.process_include_path (ixx_name) << endl
+ << endl;
+
+ hxx << "#include <xsde/cxx/post.hxx>" << endl
+ << endl;
+ }
+
+ // Copy epilogue.
+ //
+ hxx << "// Begin epilogue." << endl
+ << "//" << endl;
+
+ append (hxx, ops.value<CLI::hxx_epilogue_file> (), epilogue);
+ append (
+ hxx, ops.value<CLI::hxx_epilogue> (), ops.value<CLI::epilogue> ());
+
+ hxx << "//" << endl
+ << "// End epilogue." << endl
+ << endl;
+
+ hxx << "#endif // " << guard << endl;
+
+ if (show_sloc)
+ {
+ wcerr << hxx_path << ": "
+ << hxx_sloc.buffer ().count () << endl;
+
+ sloc += hxx_sloc.buffer ().count ();
+ }
+ }
+
+
+ // IXX
+ //
+ if (inline_)
+ {
+ Context ctx (ixx, schema, ops, &hxx_expr, &ixx_expr, &hxx_impl_expr);
+
+ Indentation::Clip<Indentation::SLOC, WideChar> ixx_sloc (ixx);
+
+
+ // Copy prologue.
+ //
+ ixx << "// Begin prologue." << endl
+ << "//" << endl;
+
+ append (
+ ixx, ops.value<CLI::ixx_prologue> (), ops.value<CLI::prologue> ());
+ append (ixx, ops.value<CLI::ixx_prologue_file> (), prologue);
+
+ ixx << "//" << endl
+ << "// End prologue." << endl
+ << endl;
+
+ {
+ // Set auto-indentation.
+ //
+ Indentation::Clip<Indentation::CXX, WideChar> ixx_clip (ixx);
+
+
+ // Generate.
+ //
+ generate_serializer_inline (ctx);
+ }
+
+ // Copy epilogue.
+ //
+ ixx << "// Begin epilogue." << endl
+ << "//" << endl;
+
+ append (ixx, ops.value<CLI::ixx_epilogue_file> (), epilogue);
+ append (
+ ixx, ops.value<CLI::ixx_epilogue> (), ops.value<CLI::epilogue> ());
+
+ ixx << "//" << endl
+ << "// End epilogue." << endl
+ << endl;
+
+ if (show_sloc)
+ {
+ wcerr << ixx_path << ": "
+ << ixx_sloc.buffer ().count () << endl;
+
+ sloc += ixx_sloc.buffer ().count ();
+ }
+ }
+
+
+ // CXX
+ //
+ if (source)
+ {
+ Context ctx (cxx, schema, ops, &hxx_expr, &ixx_expr, &hxx_impl_expr);
+
+ Indentation::Clip<Indentation::SLOC, WideChar> cxx_sloc (cxx);
+
+ // Copy prologue.
+ //
+ cxx << "// Begin prologue." << endl
+ << "//" << endl;
+
+ append (
+ cxx, ops.value<CLI::cxx_prologue> (), ops.value<CLI::prologue> ());
+ append (cxx, ops.value<CLI::cxx_prologue_file> (), prologue);
+
+ cxx << "//" << endl
+ << "// End prologue." << endl
+ << endl;
+
+ {
+ // Set auto-indentation.
+ //
+ Indentation::Clip<Indentation::CXX, WideChar> cxx_clip (cxx);
+
+ cxx << "#include " << ctx.process_include_path (hxx_name) << endl
+ << endl;
+
+ if (!inline_)
+ generate_serializer_inline (ctx);
+
+ generate_serializer_source (ctx);
+
+ if (validation)
+ {
+ generate_element_validation_source (ctx);
+ generate_attribute_validation_source (ctx);
+ }
+ }
+
+ // Copy epilogue.
+ //
+ cxx << "// Begin epilogue." << endl
+ << "//" << endl;
+
+ append (cxx, ops.value<CLI::cxx_epilogue_file> (), epilogue);
+ append (
+ cxx, ops.value<CLI::cxx_epilogue> (), ops.value<CLI::epilogue> ());
+
+ cxx << "//" << endl
+ << "// End epilogue." << endl
+ << endl;
+
+ if (show_sloc)
+ {
+ wcerr << cxx_path << ": "
+ << cxx_sloc.buffer ().count () << endl;
+
+ sloc += cxx_sloc.buffer ().count ();
+ }
+ }
+
+ // HXX impl
+ //
+ if (impl)
+ {
+ Context ctx (hxx_impl, schema, ops, &hxx_expr, &ixx_expr, &hxx_impl_expr);
+
+ String guard (guard_expr.merge (guard_prefix + hxx_impl_name));
+ guard = ctx.escape (guard); // Make it a C++ id.
+ std::transform (guard.begin (), guard.end(), guard.begin (), upcase);
+
+ hxx_impl << "#ifndef " << guard << endl
+ << "#define " << guard << endl
+ << endl;
+
+ {
+ // Set auto-indentation.
+ //
+ Indentation::Clip<Indentation::CXX, WideChar> clip (hxx_impl);
+
+ hxx_impl << "#include " << ctx.process_include_path (hxx_name)
+ << endl << endl;
+
+ generate_impl_header (ctx);
+ }
+
+ hxx_impl << "#endif // " << guard << endl;
+ }
+
+ // CXX impl
+ //
+ if (impl)
+ {
+ Context ctx (cxx_impl, schema, ops,
+ &hxx_expr, &ixx_expr, &hxx_impl_expr);
+
+ // Set auto-indentation.
+ //
+ Indentation::Clip<Indentation::CXX, WideChar> clip (cxx_impl);
+
+ cxx_impl << "#include " << ctx.process_include_path (hxx_impl_name)
+ << endl << endl;
+
+ generate_impl_source (ctx);
+ }
+
+ // CXX driver
+ //
+ if (driver)
+ {
+ Context ctx (cxx_driver, schema, ops,
+ &hxx_expr, &ixx_expr, &hxx_impl_expr);
+
+ // Set auto-indentation.
+ //
+ Indentation::Clip<Indentation::CXX, WideChar> clip (cxx_driver);
+
+ cxx_driver << "#include " << ctx.process_include_path (hxx_impl_name)
+ << endl << endl;
+
+ generate_driver_source (ctx);
+ }
+
+ return sloc;
+ }
+ catch (NoNamespaceMapping const& e)
+ {
+ wcerr << e.file () << ":" << e.line () << ":" << e.column ()
+ << ": error: unable to map XML Schema namespace '" << e.ns ()
+ << "' to C++ namespace" << endl;
+
+ wcerr << e.file () << ":" << e.line () << ":" << e.column ()
+ << ": info: use the --namespace-map or --namespace-regex option "
+ << "to provide custom mapping" << endl;
+
+ throw Failed ();
+ }
+ catch (InvalidNamespaceMapping const& e)
+ {
+ wcerr << "error: invalid XML to C++ namespace mapping specified: "
+ << "'" << e.mapping () << "': " << e.reason () << endl;
+
+ throw Failed ();
+ }
+ catch (BackendElements::Regex::Format<Char> const& e)
+ {
+ wcerr << "error: invalid regex: '" <<
+ e.expression ().c_str () << "': " <<
+ e.description ().c_str () << endl;
+
+ throw Failed ();
+ }
+ catch (BackendElements::Regex::Format<WideChar> const& e)
+ {
+ wcerr << "error: invalid regex: '" <<
+ e.expression () << "': " << e.description () << endl;
+
+ throw Failed ();
+ }
+ }
+}
diff --git a/xsde/cxx/serializer/generator.hxx b/xsde/cxx/serializer/generator.hxx
new file mode 100644
index 0000000..a5b8558
--- /dev/null
+++ b/xsde/cxx/serializer/generator.hxx
@@ -0,0 +1,56 @@
+// file : xsde/cxx/serializer/generator.hxx
+// author : Boris Kolpackov <boris@codesynthesis.com>
+// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC
+// license : GNU GPL v2 + exceptions; see accompanying LICENSE file
+
+#ifndef CXX_SERIALIZER_GENERATOR_HXX
+#define CXX_SERIALIZER_GENERATOR_HXX
+
+#include <cult/types.hxx>
+
+#include <cult/containers/vector.hxx>
+
+#include <cult/cli/options.hxx>
+#include <cult/cli/options-spec.hxx>
+
+#include <xsd-frontend/semantic-graph/elements.hxx> // Path
+#include <xsd-frontend/semantic-graph/schema.hxx>
+
+#include <xsde.hxx>
+#include <type-map/type-map.hxx>
+#include <cxx/serializer/cli.hxx>
+
+namespace CXX
+{
+ namespace Serializer
+ {
+ using namespace Cult::Types;
+
+ class Generator
+ {
+ public:
+ static Void
+ usage ();
+
+ static CLI::OptionsSpec
+ options_spec ();
+
+ struct Failed {};
+
+ static UnsignedLong
+ generate (CLI::Options const& options,
+ XSDFrontend::SemanticGraph::Schema&,
+ XSDFrontend::SemanticGraph::Path const& file,
+ TypeMap::Namespaces& type_map,
+ Boolean gen_driver,
+ const WarningSet& disabled_warnings,
+ FileList& file_list,
+ AutoUnlinks& unlinks);
+
+ private:
+ Generator ();
+ };
+ }
+}
+
+#endif // CXX_SERIALIZER_GENERATOR_HXX
diff --git a/xsde/cxx/serializer/impl-header.cxx b/xsde/cxx/serializer/impl-header.cxx
new file mode 100644
index 0000000..d98b6af
--- /dev/null
+++ b/xsde/cxx/serializer/impl-header.cxx
@@ -0,0 +1,488 @@
+// file : xsde/cxx/serializer/impl-header.cxx
+// author : Boris Kolpackov <boris@codesynthesis.com>
+// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC
+// license : GNU GPL v2 + exceptions; see accompanying LICENSE file
+
+#include <cxx/serializer/impl-header.hxx>
+
+#include <xsd-frontend/semantic-graph.hxx>
+#include <xsd-frontend/traversal.hxx>
+
+namespace CXX
+{
+ namespace Serializer
+ {
+ namespace
+ {
+ struct Enumeration: Traversal::Enumeration, Context
+ {
+ Enumeration (Context& c)
+ : Context (c)
+ {
+ }
+
+ virtual Void
+ traverse (Type& e)
+ {
+ String const& name (eimpl (e));
+ String const& arg (arg_type (e));
+ SemanticGraph::Type& base (e.inherits ().base ());
+
+ os << "class " << name << ": " << "public " <<
+ (mixin ? "virtual " : "") << ename (e);
+
+ if (mixin)
+ os << "," << endl
+ << " public " << fq_name (base, "s:impl");
+
+ os << "{"
+ << "public:" << endl;
+
+ if (tiein)
+ os << name << " ();"
+ << endl;
+
+ os << "virtual void" << endl;
+
+ if (arg == L"void")
+ os << "pre ();";
+ else
+ os << "pre (" << arg << ");";
+
+ os << endl
+ << "virtual void" << endl
+ << "post ();";
+
+ if (tiein)
+ os << endl
+ << "private:" << endl
+ << fq_name (base, "s:impl") << " base_impl_;";
+
+ os << "};";
+ }
+ };
+
+ //
+ //
+ struct List: Traversal::List, Context
+ {
+ List (Context& c)
+ : Context (c)
+ {
+ }
+
+ virtual Void
+ traverse (Type& l)
+ {
+ String const& name (eimpl (l));
+ SemanticGraph::Type& t (l.argumented ().type ());
+
+ String const& arg (arg_type (l));
+ String const& ret (ret_type (t));
+
+ String const& skel (ename (l));
+ String item (unclash (skel, "item"));
+ String item_next (unclash (skel, "item_next"));
+
+ os << "class " << name << ": public " <<
+ (mixin ? "virtual " : "") << ename (l)
+ << "{"
+ << "public:" << endl
+ << "virtual void" << endl;
+
+ if (arg == L"void")
+ os << "pre ();";
+ else
+ os << "pre (" << arg << ");";
+
+ os << endl
+ << "virtual bool" << endl
+ << item_next << " ();"
+ << endl
+ << "virtual " << ret << endl
+ << item << " ();"
+ << endl
+ << "virtual void" << endl
+ << "post ();"
+ << "};";
+ }
+ };
+
+ struct Union: Traversal::Union, Context
+ {
+ Union (Context& c)
+ : Context (c)
+ {
+ }
+
+ virtual Void
+ traverse (Type& u)
+ {
+ String const& name (eimpl (u));
+ String const& arg (arg_type (u));
+
+ os << "class " << name << ": public " <<
+ (mixin ? "virtual " : "") << ename (u)
+ << "{"
+ << "public:" << endl
+ << "virtual void" << endl;
+
+ if (arg == L"void")
+ os << "pre ();";
+ else
+ os << "pre (" << arg << ");";
+
+ os << endl
+ << "virtual void" << endl
+ << "_serialize_content ();"
+ << endl
+ << "virtual void" << endl
+ << "post ();"
+ << "};";
+ }
+ };
+
+
+ //
+ //
+ struct CompositorCallback: Traversal::All,
+ Traversal::Choice,
+ Traversal::Sequence,
+ Context
+ {
+ CompositorCallback (Context& c)
+ : Context (c)
+ {
+ }
+
+ virtual Void
+ traverse (SemanticGraph::All& a)
+ {
+ // For the all compositor, maxOccurs=1 and minOccurs={0,1}.
+ //
+ if (a.min () == 0)
+ {
+ os << "virtual bool" << endl
+ << epresent (a) << " ();"
+ << endl;
+ }
+
+ Traversal::All::traverse (a);
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Choice& c)
+ {
+ if (c.contains_begin () != c.contains_end ())
+ {
+ UnsignedLong min (c.min ()), max (c.max ());
+
+ if (min == 0 && max == 1)
+ {
+ os << "virtual bool" << endl
+ << epresent (c) << " ();"
+ << endl;
+ }
+ else if (max != 1)
+ {
+ os << "virtual bool" << endl
+ << enext (c) << " ();"
+ << endl;
+ }
+
+ os << "virtual " << earm_tag (c) << endl
+ << earm (c) << " ();"
+ << endl;
+
+ Traversal::Choice::traverse (c);
+ }
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Sequence& s)
+ {
+ UnsignedLong min (s.min ()), max (s.max ());
+
+ if (min == 0 && max == 1)
+ {
+ os << "virtual bool" << endl
+ << epresent (s) << " ();"
+ << endl;
+ }
+ else if (max != 1)
+ {
+ os << "virtual bool" << endl
+ << enext (s) << " ();"
+ << endl;
+ }
+
+ Traversal::Sequence::traverse (s);
+ }
+ };
+
+ struct ParticleCallback: Traversal::Element,
+ Traversal::Any,
+ Context
+ {
+ ParticleCallback (Context& c)
+ : Context (c)
+ {
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Element& e)
+ {
+ UnsignedLong min (e.min ()), max (e.max ());
+
+ if (min == 0 && max == 1)
+ {
+ os << "virtual bool" << endl
+ << epresent (e) << " ();"
+ << endl;
+ }
+ else if (max != 1)
+ {
+ os << "virtual bool" << endl
+ << enext (e) << " ();"
+ << endl;
+ }
+
+ String const& ret (ret_type (e.type ()));
+
+ os << "virtual " << ret << endl
+ << ename (e) << " ();"
+ << endl;
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Any& a)
+ {
+ UnsignedLong min (a.min ()), max (a.max ());
+
+ if (min == 0 && max == 1)
+ {
+ os << "virtual bool" << endl
+ << epresent (a) << " ();"
+ << endl;
+ }
+ else if (max != 1)
+ {
+ os << "virtual bool" << endl
+ << enext (a) << " ();"
+ << endl;
+ }
+
+ if (stl)
+ {
+ os << "virtual void" << endl
+ << ename (a) << " (::std::string& ns, ::std::string& name);"
+ << endl;
+ }
+ else
+ {
+ os << "virtual void" << endl
+ << ename (a) << " (const char*& ns, const char*& name, " <<
+ "bool& free);"
+ << endl;
+ }
+
+ os << "virtual void" << endl
+ << eserialize (a) << " ();"
+ << endl;
+
+ }
+ };
+
+ struct AttributeCallback: Traversal::Attribute,
+ Traversal::AnyAttribute,
+ Context
+ {
+ AttributeCallback (Context& c)
+ : Context (c)
+ {
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Attribute& a)
+ {
+ if (a.optional ())
+ {
+ os << "virtual bool" << endl
+ << epresent (a) << " ();"
+ << endl;
+ }
+
+ String const& ret (ret_type (a.type ()));
+
+ os << "virtual " << ret << endl
+ << ename (a) << " ();"
+ << endl;
+ }
+
+ virtual Void
+ traverse (SemanticGraph::AnyAttribute& a)
+ {
+ os << "virtual bool" << endl
+ << enext (a) << " ();"
+ << endl;
+
+ if (stl)
+ {
+ os << "virtual void" << endl
+ << ename (a) << " (::std::string& ns, ::std::string& name);"
+ << endl;
+ }
+ else
+ {
+ os << "virtual void" << endl
+ << ename (a) << " (const char*& ns, const char*& name, " <<
+ "bool& free);"
+ << endl;
+ }
+
+ os << "virtual void" << endl
+ << eserialize (a) << " ();"
+ << endl;
+ }
+ };
+
+ //
+ //
+ struct Complex : Traversal::Complex, Context
+ {
+ Complex (Context& c)
+ : Context (c),
+ compositor_callback_ (c),
+ particle_callback_ (c),
+ attribute_callback_ (c)
+ {
+ contains_compositor_callback_ >> compositor_callback_;
+ compositor_callback_ >> contains_particle_callback_;
+ contains_particle_callback_ >> compositor_callback_;
+ contains_particle_callback_ >> particle_callback_;
+
+ names_attribute_callback_ >> attribute_callback_;
+ }
+
+ virtual Void
+ traverse (Type& c)
+ {
+ // In case of an inheritance-by-restriction, we don't need to
+ // generate serializer callbacks, etc. since they are the same
+ // as in the base. We only need the serialization/validation code.
+ //
+ Boolean restriction (restriction_p (c));
+
+ Boolean hb (c.inherits_p ());
+ Boolean he (has<Traversal::Element> (c));
+ Boolean ha (has<Traversal::Attribute> (c));
+
+ Boolean hae (has_particle<Traversal::Any> (c));
+ Boolean haa (has<Traversal::AnyAttribute> (c));
+
+ String const& name (eimpl (c));
+ String const& arg (arg_type (c));
+
+ os << "class " << name << ": public " <<
+ (mixin ? "virtual " : "") << ename (c);
+
+ if (mixin && hb)
+ os << "," << endl
+ << " public " << fq_name (c.inherits ().base (), "s:impl");
+
+ os << "{"
+ << "public:" << endl;
+
+ // c-tor
+ //
+ if (tiein && hb)
+ os << name << " ();"
+ << endl;
+
+ // pre
+ //
+ os << "virtual void" << endl;
+
+ if (arg == L"void")
+ os << "pre ();";
+ else
+ os << "pre (" << arg << ");";
+
+ os << endl;
+
+
+ // Member callbacks.
+ //
+ if (!restriction && (ha || he || hae || haa))
+ {
+ if (ha || haa)
+ {
+ os << "// Attributes." << endl
+ << "//" << endl;
+
+ names (c, names_attribute_callback_);
+ }
+
+ if (he || hae)
+ {
+ os << "// Elements." << endl
+ << "//" << endl;
+
+ contains_compositor (c, contains_compositor_callback_);
+ }
+ }
+
+ // post
+ //
+ os << "virtual void" << endl
+ << "post ();";
+
+ if (tiein && hb)
+ os << endl
+ << "private:" << endl
+ << fq_name (c.inherits ().base (), "s:impl") << " base_impl_;";
+
+ os << "};";
+ }
+
+ private:
+ CompositorCallback compositor_callback_;
+ ParticleCallback particle_callback_;
+ Traversal::ContainsCompositor contains_compositor_callback_;
+ Traversal::ContainsParticle contains_particle_callback_;
+
+ AttributeCallback attribute_callback_;
+ Traversal::Names names_attribute_callback_;
+ };
+ }
+
+ Void
+ generate_impl_header (Context& ctx)
+ {
+ Traversal::Schema schema;
+
+ Traversal::Sources sources;
+ Includes includes (ctx, Includes::impl_header);
+ Traversal::Names schema_names;
+
+ Namespace ns (ctx);
+ Traversal::Names names;
+
+ schema >> includes;
+ schema >> sources >> schema;
+ schema >> schema_names >> ns >> names;
+
+ List list (ctx);
+ Union union_ (ctx);
+ Complex complex (ctx);
+ Enumeration enumeration (ctx);
+
+ names >> list;
+ names >> union_;
+ names >> complex;
+ names >> enumeration;
+
+ schema.dispatch (ctx.schema_root);
+ }
+ }
+}
diff --git a/xsde/cxx/serializer/impl-header.hxx b/xsde/cxx/serializer/impl-header.hxx
new file mode 100644
index 0000000..a483eaa
--- /dev/null
+++ b/xsde/cxx/serializer/impl-header.hxx
@@ -0,0 +1,22 @@
+// file : xsde/cxx/serializer/impl-header.hxx
+// author : Boris Kolpackov <boris@codesynthesis.com>
+// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC
+// license : GNU GPL v2 + exceptions; see accompanying LICENSE file
+
+#ifndef CXX_SERIALIZER_IMPL_HEADER_HXX
+#define CXX_SERIALIZER_IMPL_HEADER_HXX
+
+#include <xsd-frontend/semantic-graph/schema.hxx>
+
+#include <cxx/serializer/elements.hxx>
+
+namespace CXX
+{
+ namespace Serializer
+ {
+ Void
+ generate_impl_header (Context&);
+ }
+}
+
+#endif // CXX_SERIALIZER_IMPL_HEADER_HXX
diff --git a/xsde/cxx/serializer/impl-source.cxx b/xsde/cxx/serializer/impl-source.cxx
new file mode 100644
index 0000000..cc31ced
--- /dev/null
+++ b/xsde/cxx/serializer/impl-source.cxx
@@ -0,0 +1,664 @@
+// file : xsde/cxx/serializer/impl-source.cxx
+// author : Boris Kolpackov <boris@codesynthesis.com>
+// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC
+// license : GNU GPL v2 + exceptions; see accompanying LICENSE file
+
+#include <cxx/serializer/impl-source.hxx>
+
+#include <xsd-frontend/semantic-graph.hxx>
+#include <xsd-frontend/traversal.hxx>
+
+namespace CXX
+{
+ namespace Serializer
+ {
+ namespace
+ {
+ struct Enumeration: Traversal::Enumeration, Context
+ {
+ Enumeration (Context& c)
+ : Context (c)
+ {
+ }
+
+ virtual Void
+ traverse (Type& e)
+ {
+ String const& name (eimpl (e));
+ String const& arg (arg_type (e));
+ SemanticGraph::Type& base (e.inherits ().base ());
+
+ os << "// " << name << endl
+ << "//" << endl
+ << endl;
+
+ // c-tor
+ //
+ if (tiein)
+ os << name << "::" << endl
+ << name << " ()" << endl
+ << ": " << ename (e) << " (&base_impl_)"
+ << "{"
+ << "}";
+
+ // pre
+ //
+ os << "void " << name << "::" << endl;
+
+ if (arg == L"void")
+ os << "pre ()";
+ else
+ os << "pre (" << arg << " v)";
+
+ os << "{";
+
+ if (arg == arg_type (base))
+ {
+ if (tiein)
+ {
+ os << "base_impl_.pre (" <<
+ (arg != L"void" ? "v" : "") << ");";
+ }
+ else if (mixin)
+ {
+ os << eimpl (base) << "::pre (" <<
+ (arg != L"void" ? "v" : "") << ");";
+ }
+ }
+ else
+ {
+ if (tiein)
+ {
+ os << "// TODO: call base_impl_.pre ()." << endl
+ << "//" << endl;
+ }
+ else if (mixin)
+ {
+ os << "// TODO: call " << eimpl (base) << "::pre ()." << endl
+ << "//" << endl;
+ }
+ }
+
+ os << "}";
+
+ // post
+ //
+ os << "void " << name << "::" << endl
+ << "post ()"
+ << "{"
+ << "}";
+ }
+ };
+
+ //
+ //
+ struct List: Traversal::List, Context
+ {
+ List (Context& c)
+ : Context (c)
+ {
+ }
+
+ virtual Void
+ traverse (Type& l)
+ {
+ String const& name (eimpl (l));
+ SemanticGraph::Type& t (l.argumented ().type ());
+
+ String const& arg (arg_type (l));
+ String const& ret (ret_type (t));
+
+ String const& skel (ename (l));
+ String item (unclash (skel, "item"));
+ String item_next (unclash (skel, "item_next"));
+
+ os << "// " << name << endl
+ << "//" << endl
+ << endl;
+
+ // pre
+ //
+ os << "void " << name << "::" << endl;
+
+ if (arg == L"void")
+ os << "pre ()"
+ << "{"
+ << "}";
+ else
+ os << "pre (" << arg << " v)"
+ << "{"
+ << "// TODO" << endl
+ << "//" << endl
+ << "}";
+
+ // item
+ //
+ os << "bool " << name << "::" << endl
+ << item_next << " ()"
+ << "{"
+ << "// TODO: return true if there is another item to" << endl
+ << "// serialize." << endl
+ << "//" << endl
+ << "}";
+
+
+ os << ret << " " << name << "::" << endl
+ << item << " ()"
+ << "{"
+ << "// TODO: return the next item." << endl
+ << "//" << endl
+ << "}";
+
+ // post
+ //
+ os << "void " << name << "::" << endl
+ << "post ()"
+ << "{"
+ << "}";
+ }
+ };
+
+ //
+ //
+ struct Union: Traversal::Union, Context
+ {
+ Union (Context& c)
+ : Context (c)
+ {
+ }
+
+ virtual Void
+ traverse (Type& u)
+ {
+ String const& name (eimpl (u));
+ String const& arg (arg_type (u));
+
+ os << "// " << name << endl
+ << "//" << endl
+ << endl;
+
+ // pre
+ //
+ os << "void " << name << "::" << endl;
+
+ if (arg == L"void")
+ os << "pre ()"
+ << "{"
+ << "}";
+ else
+ os << "pre (" << arg << " v)"
+ << "{"
+ << "// TODO" << endl
+ << "//" << endl
+ << "}";
+
+ // _serialize_content
+ //
+ os << "void " << name << "::" << endl
+ << "_serialize_content ()"
+ << "{"
+ << "// TODO: call the _characters() function to serialize" << endl
+ << "// text content." << endl
+ << "//" << endl
+ << "}";
+
+ // post
+ //
+ os << "void " << name << "::" << endl
+ << "post ()"
+ << "{"
+ << "}";
+ }
+ };
+
+ //
+ //
+ struct CompositorCallback: Traversal::All,
+ Traversal::Choice,
+ Traversal::Sequence,
+ Context
+ {
+ CompositorCallback (Context& c)
+ : Context (c)
+ {
+ }
+
+ virtual Void
+ traverse (SemanticGraph::All& a)
+ {
+ // For the all compositor, maxOccurs=1 and minOccurs={0,1}.
+ //
+ if (a.min () == 0)
+ {
+ String const& s (eimpl (scope (a)));
+
+ os << "bool " << s << "::" << endl
+ << epresent (a) << " ()"
+ << "{"
+ << "// TODO: return true if the content corresponding" << endl
+ << "// to the all compositor is present." << endl
+ << "//" << endl
+ << "}";
+ }
+
+ Traversal::All::traverse (a);
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Choice& c)
+ {
+ if (c.contains_begin () != c.contains_end ())
+ {
+ UnsignedLong min (c.min ()), max (c.max ());
+
+ SemanticGraph::Complex& t (scope (c));
+ String const& s (eimpl (t));
+
+ if (min == 0 && max == 1)
+ {
+ os << "bool " << s << "::" << endl
+ << epresent (c) << " ()"
+ << "{"
+ << "// TODO: return true if the content corresponding" << endl
+ << "// to the choice compositor is present." << endl
+ << "//" << endl
+ << "}";
+ }
+ else if (max != 1)
+ {
+ os << "bool " << s << "::" << endl
+ << enext (c) << " ()"
+ << "{"
+ << "// TODO: return true if there is another choice" << endl
+ << "// item to serialize." << endl
+ << "//" << endl
+ << "}";
+ }
+
+ os << ename (t) << "::" << earm_tag (c) << " " << s << "::" << endl
+ << earm (c) << " ()"
+ << "{"
+ << "// TODO: return the choice arm that is being" << endl
+ << "// serialized." << endl
+ << "//" << endl
+ << "}";
+
+ Traversal::Choice::traverse (c);
+ }
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Sequence& s)
+ {
+ UnsignedLong min (s.min ()), max (s.max ());
+
+ String const& sc (eimpl (scope (s)));
+
+ if (min == 0 && max == 1)
+ {
+ os << "bool " << sc << "::" << endl
+ << epresent (s) << " ()"
+ << "{"
+ << "// TODO: return true if the content corresponding" << endl
+ << "// to the sequence compositor is present." << endl
+ << "//" << endl
+ << "}";
+
+ }
+ else if (max != 1)
+ {
+ os << "bool " << sc << "::" << endl
+ << enext (s) << " ()"
+ << "{"
+ << "// TODO: return true if there is another sequence" << endl
+ << "// item to serialize." << endl
+ << "//" << endl
+ << "}";
+ }
+
+ Traversal::Sequence::traverse (s);
+ }
+
+ private:
+ SemanticGraph::Complex&
+ scope (SemanticGraph::Compositor& c)
+ {
+ SemanticGraph::Compositor* root (&c);
+
+ while (root->contained_particle_p ())
+ root = &root->contained_particle ().compositor ();
+
+ return dynamic_cast<SemanticGraph::Complex&> (
+ root->contained_compositor ().container ());
+ }
+ };
+
+ struct ParticleCallback: Traversal::Element,
+ Traversal::Any,
+ Context
+ {
+ ParticleCallback (Context& c)
+ : Context (c)
+ {
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Element& e)
+ {
+ UnsignedLong min (e.min ()), max (e.max ());
+
+ String const& s (
+ eimpl (dynamic_cast<SemanticGraph::Complex&> (e.scope ())));
+
+ if (min == 0 && max == 1)
+ {
+ os << "bool " << s << "::" << endl
+ << epresent (e) << " ()"
+ << "{"
+ << "// TODO: return true if the element is present." << endl
+ << "//" << endl
+ << "}";
+
+ }
+ else if (max != 1)
+ {
+ os << "bool " << s << "::" << endl
+ << enext (e) << " ()"
+ << "{"
+ << "// TODO: return true if there is another element" << endl
+ << "// to serialize." << endl
+ << "//" << endl
+ << "}";
+ }
+
+ String const& ret (ret_type (e.type ()));
+
+ os << ret << " " << s << "::" << endl
+ << ename (e) << " ()"
+ << "{"
+ << "// TODO: return the element data." << endl
+ << "//" << endl
+ << "}";
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Any& a)
+ {
+ UnsignedLong min (a.min ()), max (a.max ());
+
+ String const& s (
+ eimpl (dynamic_cast<SemanticGraph::Complex&> (a.scope ())));
+
+ if (min == 0 && max == 1)
+ {
+ os << "bool " << s << "::" << endl
+ << epresent (a) << " ()"
+ << "{"
+ << "// TODO: return true if the wildcard content is" << endl
+ << "// present." << endl
+ << "//" << endl
+ << "}";
+ }
+ else if (max != 1)
+ {
+ os << "bool " << s << "::" << endl
+ << enext (a) << " ()"
+ << "{"
+ << "// TODO: return true if there is another wildcard" << endl
+ << "// element to serialize." << endl
+ << "//" << endl
+ << "}";
+ }
+
+ if (stl)
+ {
+ os << "void " << s << "::" << endl
+ << ename (a) << " (::std::string& ns, ::std::string& name)";
+ }
+ else
+ {
+ os << "void " << s << "::" << endl
+ << ename (a) << " (const char*& ns, const char*& name, " <<
+ "bool& free)";
+ }
+
+ os << "{"
+ << "// TODO: return the name and namespace of the element" << endl
+ << "// corresponding to the wildcard." << endl
+ << "//" << endl
+ << "}";
+
+ os << "void " << s << "::" << endl
+ << eserialize (a) << " ()"
+ << "{"
+ << "// TODO: use the _start_element(), _end_element()," << endl
+ << "// _attribute(), and _characters() functions to" << endl
+ << "// serialize the wildcard content." << endl
+ << "//" << endl
+ << "}";
+
+ }
+ };
+
+ struct AttributeCallback: Traversal::Attribute,
+ Traversal::AnyAttribute,
+ Context
+ {
+ AttributeCallback (Context& c)
+ : Context (c)
+ {
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Attribute& a)
+ {
+ String const& s (
+ eimpl (dynamic_cast<SemanticGraph::Complex&> (a.scope ())));
+
+ if (a.optional ())
+ {
+ os << "bool " << s << "::" << endl
+ << epresent (a) << " ()"
+ << "{"
+ << "// TODO: return true if the attribute is present." << endl
+ << "//" << endl
+ << "}";
+ }
+
+ String const& ret (ret_type (a.type ()));
+
+ os << ret << " " << s << "::" << endl
+ << ename (a) << " ()"
+ << "{"
+ << "// TODO: return the attribute data." << endl
+ << "//" << endl
+ << "}";
+ }
+
+ virtual Void
+ traverse (SemanticGraph::AnyAttribute& a)
+ {
+ String const& s (
+ eimpl (dynamic_cast<SemanticGraph::Complex&> (a.scope ())));
+
+ os << "bool " << s << "::" << endl
+ << enext (a) << " ()"
+ << "{"
+ << "// TODO: return true if there is another wildcard" << endl
+ << "// attribute to serialize." << endl
+ << "//" << endl
+ << "}";
+
+ if (stl)
+ {
+ os << "void " << s << "::" << endl
+ << ename (a) << " (::std::string& ns, ::std::string& name)";
+ }
+ else
+ {
+ os << "void " << s << "::" << endl
+ << ename (a) << " (const char*& ns, const char*& name, " <<
+ "bool& free)";
+ }
+
+ os << "{"
+ << "// TODO: return the name and namespace of the attribute" << endl
+ << "// corresponding to the wildcard." << endl
+ << "//" << endl
+ << "}";
+
+ os << "void " << s << "::" << endl
+ << eserialize (a) << " ()"
+ << "{"
+ << "// TODO: use the _characters() function to serialize" << endl
+ << "// the wildcard content." << endl
+ << "//" << endl
+ << "}";
+ }
+ };
+
+ //
+ //
+ struct Complex : Traversal::Complex, Context
+ {
+ Complex (Context& c)
+ : Context (c),
+ compositor_callback_ (c),
+ particle_callback_ (c),
+ attribute_callback_ (c)
+ {
+ contains_compositor_callback_ >> compositor_callback_;
+ compositor_callback_ >> contains_particle_callback_;
+ contains_particle_callback_ >> compositor_callback_;
+ contains_particle_callback_ >> particle_callback_;
+
+ names_attribute_callback_ >> attribute_callback_;
+ }
+
+ virtual Void
+ traverse (Type& c)
+ {
+ Boolean hb (c.inherits_p ());
+
+ String const& name (eimpl (c));
+ String const& arg (arg_type (c));
+
+ os << "// " << name << endl
+ << "//" << endl
+ << endl;
+
+ // c-tor
+ //
+ if (tiein && hb)
+ os << name << "::" << endl
+ << name << " ()" << endl
+ << ": " << ename (c) << " (&base_impl_)"
+ << "{"
+ << "}";
+
+ // pre
+ //
+ os << "void " << name << "::" << endl;
+
+ if (arg == L"void")
+ os << "pre ()";
+ else
+ os << "pre (" << arg << " v)";
+
+ os << "{";
+
+ if (hb)
+ {
+ SemanticGraph::Type& base (c.inherits ().base ());
+
+ if (arg == arg_type (base))
+ {
+ if (tiein)
+ {
+ os << "base_impl_.pre (" <<
+ (arg != L"void" ? "v" : "") << ");";
+ }
+ else if (mixin)
+ {
+ os << eimpl (base) << "::pre (" <<
+ (arg != L"void" ? "v" : "") << ");";
+ }
+ }
+ else
+ {
+ if (tiein)
+ {
+ os << "// TODO: call " << eimpl (base) << "::pre ()." << endl
+ << "//" << endl;
+ }
+ else if (mixin)
+ {
+ os << "// TODO: call base_impl_.pre ()." << endl
+ << "//" << endl;
+ }
+ }
+
+ }
+ else if (arg != L"void")
+ {
+ os << "// TODO" << endl
+ << "//" << endl;
+ }
+
+ os << "}";
+
+ // Member callbacks.
+ //
+ if (!restriction_p (c))
+ {
+ names (c, names_attribute_callback_);
+ contains_compositor (c, contains_compositor_callback_);
+ }
+
+ // post
+ //
+ os << "void " << name << "::" << endl
+ << "post ()"
+ << "{"
+ << "}";
+ }
+
+ private:
+ CompositorCallback compositor_callback_;
+ ParticleCallback particle_callback_;
+ Traversal::ContainsCompositor contains_compositor_callback_;
+ Traversal::ContainsParticle contains_particle_callback_;
+
+ AttributeCallback attribute_callback_;
+ Traversal::Names names_attribute_callback_;
+ };
+ }
+
+ Void
+ generate_impl_source (Context& ctx)
+ {
+ Traversal::Schema schema;
+
+ Traversal::Sources sources;
+ Traversal::Names schema_names;
+
+ Namespace ns (ctx);
+ Traversal::Names names;
+
+ schema >> sources >> schema;
+ schema >> schema_names >> ns >> names;
+
+ List list (ctx);
+ Union union_ (ctx);
+ Complex complex (ctx);
+ Enumeration enumeration (ctx);
+
+ names >> list;
+ names >> union_;
+ names >> complex;
+ names >> enumeration;
+
+ schema.dispatch (ctx.schema_root);
+ }
+ }
+}
diff --git a/xsde/cxx/serializer/impl-source.hxx b/xsde/cxx/serializer/impl-source.hxx
new file mode 100644
index 0000000..f6303ba
--- /dev/null
+++ b/xsde/cxx/serializer/impl-source.hxx
@@ -0,0 +1,22 @@
+// file : xsde/cxx/serializer/impl-source.hxx
+// author : Boris Kolpackov <boris@codesynthesis.com>
+// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC
+// license : GNU GPL v2 + exceptions; see accompanying LICENSE file
+
+#ifndef CXX_SERIALIZER_IMPL_SOURCE_HXX
+#define CXX_SERIALIZER_IMPL_SOURCE_HXX
+
+#include <xsd-frontend/semantic-graph/schema.hxx>
+
+#include <cxx/serializer/elements.hxx>
+
+namespace CXX
+{
+ namespace Serializer
+ {
+ Void
+ generate_impl_source (Context&);
+ }
+}
+
+#endif // CXX_SERIALIZER_IMPL_SOURCE_HXX
diff --git a/xsde/cxx/serializer/name-processor.cxx b/xsde/cxx/serializer/name-processor.cxx
new file mode 100644
index 0000000..d68b823
--- /dev/null
+++ b/xsde/cxx/serializer/name-processor.cxx
@@ -0,0 +1,1409 @@
+// file : xsde/cxx/serializer/name-processor.cxx
+// author : Boris Kolpackov <boris@codesynthesis.com>
+// copyright : Copyright (c) 2006-2009 Code Synthesis Tools CC
+// license : GNU GPL v2 + exceptions; see accompanying LICENSE file
+
+#include <cxx/elements.hxx>
+#include <cxx/serializer/name-processor.hxx>
+
+#include <xsd-frontend/semantic-graph.hxx>
+#include <xsd-frontend/traversal.hxx>
+
+#include <cult/containers/set.hxx>
+
+#include <sstream>
+#include <iostream>
+
+namespace CXX
+{
+ namespace Serializer
+ {
+ namespace
+ {
+ //
+ //
+ typedef Cult::Containers::Set<String> NameSet;
+
+ class Context: public CXX::Context
+ {
+ public:
+ Context (CLI::Options const& ops,
+ SemanticGraph::Schema& root,
+ SemanticGraph::Path const& file)
+ : CXX::Context (std::wcerr,
+ root,
+ "s:name",
+ "char",
+ ops.value<CLI::include_with_brackets> (),
+ ops.value<CLI::include_prefix> (),
+ "", // export symbol
+ ops.value<CLI::namespace_map> (),
+ ops.value<CLI::namespace_regex> (),
+ ops.value<CLI::namespace_regex_trace> (),
+ ops.value<CLI::include_regex> (),
+ ops.value<CLI::include_regex_trace> (),
+ ops.value<CLI::generate_inline> (),
+ ops.value<CLI::reserved_name> ()),
+ schema_path_ (file),
+ skel_suffix_ (ops.value<CLI::skel_type_suffix> ()),
+ impl_suffix_ (ops.value<CLI::impl_type_suffix> ()),
+ schema (root),
+ schema_path (schema_path_),
+ impl (ops.value<CLI::generate_empty_impl> () ||
+ ops.value<CLI::generate_test_driver> ()),
+ tiein (!ops.value<CLI::reuse_style_mixin> () &&
+ !ops.value<CLI::reuse_style_none> ()),
+ skel_suffix (skel_suffix_),
+ impl_suffix (impl_suffix_),
+ global_type_names (global_type_names_),
+ validation (!ops.value<CLI::suppress_validation> ()),
+ polymorphic (ops.value<CLI::generate_polymorphic> ())
+ {
+ }
+
+ protected:
+ Context (Context& c)
+ : CXX::Context (c),
+ schema (c.schema),
+ schema_path (c.schema_path),
+ impl (c.impl),
+ tiein (c.tiein),
+ skel_suffix (c.skel_suffix),
+ impl_suffix (c.impl_suffix),
+ global_type_names (c.global_type_names),
+ validation (c.validation),
+ polymorphic (c.polymorphic)
+ {
+ }
+
+ public:
+ String
+ find_name (String const& n, String const& suffix, NameSet& set)
+ {
+ String name (escape (n + suffix));
+
+ for (UnsignedLong i (1); set.find (name) != set.end (); ++i)
+ {
+ std::wostringstream os;
+ os << i;
+ name = escape (n + os.str () + suffix);
+ }
+
+ set.insert (name);
+ return name;
+ }
+
+ String
+ find_name (String const& n, NameSet& set)
+ {
+ return find_name (n, L"", set);
+ }
+
+ private:
+ SemanticGraph::Path const schema_path_;
+ String const skel_suffix_;
+ String const impl_suffix_;
+
+ Cult::Containers::Map<String, NameSet*> global_type_names_;
+
+ public:
+ SemanticGraph::Schema& schema;
+ SemanticGraph::Path const& schema_path;
+ Boolean const impl;
+ Boolean const tiein;
+ String const& skel_suffix;
+ String const& impl_suffix;
+
+ Cult::Containers::Map<String, NameSet*>& global_type_names;
+
+ Boolean validation;
+ Boolean polymorphic;
+ };
+
+ // Primary names.
+ //
+ struct PrimaryParticle: Traversal::Element,
+ Traversal::Any,
+ Context
+ {
+ PrimaryParticle (Context& c, NameSet& set, Boolean restriction)
+ : Context (c), set_ (set), restriction_ (restriction)
+ {
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Element& e)
+ {
+ using SemanticGraph::Element;
+
+ SemanticGraph::Context& ec (e.context ());
+
+ if (!restriction_)
+ ec.set ("s:name", find_name (e.name (), set_));
+ else
+ {
+ Element* prot = ec.get<Element*> (
+ "xsd-frontend-restriction-correspondence");
+
+ ec.set ("s:name", prot->context ().get<String> ("s:name"));
+ }
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Any& a)
+ {
+ using SemanticGraph::Any;
+
+ SemanticGraph::Context& ac (a.context ());
+
+ if (!restriction_)
+ {
+ ac.set ("s:name", find_name (L"any", set_));
+ }
+ else
+ {
+ Any* prot = ac.get<Any*> (
+ "xsd-frontend-restriction-correspondence");
+
+ ac.set ("s:name", prot->context ().get<String> ("s:name"));
+ }
+ }
+
+ private:
+ NameSet& set_;
+ Boolean restriction_;
+ };
+
+ struct PrimaryAttribute: Traversal::Attribute,
+ Traversal::AnyAttribute,
+ Context
+ {
+ PrimaryAttribute (Context& c, NameSet& set, Boolean restriction)
+ : Context (c), set_ (set), restriction_ (restriction)
+ {
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Attribute& a)
+ {
+ using SemanticGraph::Attribute;
+
+ SemanticGraph::Context& ac (a.context ());
+
+ if (!restriction_)
+ {
+ ac.set ("s:name", find_name (a.name (), set_));
+ }
+ else
+ {
+ Attribute* prot = ac.get<Attribute*> (
+ "xsd-frontend-restriction-correspondence");
+
+ ac.set ("s:name", prot->context ().get<String> ("s:name"));
+ }
+ }
+
+ virtual Void
+ traverse (SemanticGraph::AnyAttribute& a)
+ {
+ using SemanticGraph::AnyAttribute;
+
+ SemanticGraph::Context& ac (a.context ());
+
+ if (!restriction_)
+ {
+ ac.set ("s:name", find_name (L"any_attribute", set_));
+ }
+ else
+ {
+ AnyAttribute* prot = ac.get<AnyAttribute*> (
+ "xsd-frontend-restriction-correspondence");
+
+ ac.set ("s:name", prot->context ().get<String> ("s:name"));
+ }
+ }
+
+ private:
+ NameSet& set_;
+ Boolean restriction_;
+ };
+
+ // Secondary names.
+ //
+
+ struct ParticleTag: Traversal::Element,
+ Traversal::Any,
+ Traversal::Choice,
+ Traversal::Sequence,
+ Context
+ {
+ ParticleTag (Context& c, NameSet& set, Boolean restriction)
+ : Context (c), set_ (set), restriction_ (restriction)
+ {
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Element& e)
+ {
+ using SemanticGraph::Element;
+
+ SemanticGraph::Context& ec (e.context ());
+
+ if (!restriction_)
+ {
+ String const base (ec.get<String> ("s:name"));
+ ec.set ("s:tag", find_name (base, L"_tag", set_));
+ }
+ else
+ {
+ Element* prot = ec.get<Element*> (
+ "xsd-frontend-restriction-correspondence");
+
+ ec.set ("s:tag", prot->context ().get<String> ("s:tag"));
+ }
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Any& a)
+ {
+ using SemanticGraph::Any;
+
+ SemanticGraph::Context& ac (a.context ());
+
+ if (!restriction_)
+ {
+ String const& base (ac.get<String> ("s:name"));
+ ac.set ("s:tag", find_name (base, L"_tag", set_));
+ }
+ else
+ {
+ Any* prot = ac.get<Any*> (
+ "xsd-frontend-restriction-correspondence");
+
+ ac.set ("s:tag", prot->context ().get<String> ("s:tag"));
+ }
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Choice& c)
+ {
+ using SemanticGraph::Compositor;
+
+ SemanticGraph::Context& cc (c.context ());
+
+ if (!restriction_)
+ {
+ cc.set ("s:tag", find_name (L"choice", L"_tag", set_));
+ }
+ else
+ {
+ Compositor* prot = cc.get<Compositor*> (
+ "xsd-frontend-restriction-correspondence");
+
+ cc.set ("s:tag", prot->context ().get<String> ("s:tag"));
+ }
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Sequence& s)
+ {
+ using SemanticGraph::Compositor;
+
+ SemanticGraph::Context& sc (s.context ());
+
+ if (!restriction_)
+ {
+ sc.set ("s:tag", find_name (L"sequence", L"_tag", set_));
+ }
+ else
+ {
+ Compositor* prot = sc.get<Compositor*> (
+ "xsd-frontend-restriction-correspondence");
+
+ sc.set ("s:tag", prot->context ().get<String> ("s:tag"));
+ }
+ }
+
+ private:
+ NameSet& set_;
+ Boolean restriction_;
+ };
+
+ struct SecondaryCompositor: Traversal::All,
+ Traversal::Choice,
+ Traversal::Sequence,
+ Context
+ {
+ SecondaryCompositor (Context& c, NameSet& set, Boolean restriction)
+ : Context (c),
+ set_ (set),
+ restriction_ (restriction),
+ particle_tag_ (c, set, restriction)
+ {
+ contain_particle_tag_ >> particle_tag_;
+ }
+
+ virtual Void
+ traverse (SemanticGraph::All& a)
+ {
+ // For the all compositor, maxOccurs=1 and minOccurs={0,1}
+ // and it cannot be used in restriction.
+ //
+ if (a.contained_compositor ().min () == 0)
+ {
+ a.context ().set (
+ "s:present", find_name (L"all", L"_present", set_));
+ }
+
+ Traversal::All::traverse (a);
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Choice& c)
+ {
+ if (c.contains_begin () == c.contains_end ())
+ return;
+
+ SemanticGraph::Context& cc (c.context ());
+
+ if (!restriction_)
+ {
+ if (c.max () != 1)
+ cc.set ("s:next", find_name (L"choice", L"_next", set_));
+ else if (c.min () == 0)
+ cc.set ("s:present", find_name (L"choice", L"_present", set_));
+
+ // Tags.
+ //
+ cc.set ("s:arm-tag", find_name (L"choice", L"_arm_tag", set_));
+ Traversal::Choice::contains (c, contain_particle_tag_);
+ cc.set ("s:arm", find_name (L"choice", L"_arm", set_));
+ }
+ else
+ {
+ SemanticGraph::Compositor& b (
+ *cc.get<SemanticGraph::Compositor*> (
+ "xsd-frontend-restriction-correspondence"));
+
+ SemanticGraph::Context& bc (b.context ());
+
+ if (b.max () != 1)
+ {
+ cc.set ("s:next", bc.get<String> ("s:next"));
+
+ // Add the *_present callback if this is a restriction
+ // of sequence to optional.
+ //
+ if (c.min () == 0)
+ cc.set ("s:present",
+ find_name (L"choice", L"_present", set_));
+ }
+ else if (b.min () == 0)
+ cc.set ("s:present", bc.get<String> ("s:present"));
+
+ // Tags.
+ //
+ cc.set ("s:arm-tag", bc.get<String> ("s:arm-tag"));
+ Traversal::Choice::contains (c, contain_particle_tag_);
+ cc.set ("s:arm", bc.get<String> ("s:arm"));
+ }
+
+ Traversal::Choice::traverse (c);
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Sequence& s)
+ {
+ SemanticGraph::Context& sc (s.context ());
+
+ if (!restriction_)
+ {
+ if (s.max () != 1)
+ sc.set ("s:next", find_name (L"sequence", L"_next", set_));
+ else if (s.min () == 0)
+ sc.set ("s:present", find_name (L"sequence", L"_present", set_));
+ }
+ else
+ {
+ // Root compositor that models inheritance by extension
+ // may not have an association.
+ //
+ if (sc.count ("xsd-frontend-restriction-correspondence"))
+ {
+ SemanticGraph::Compositor& b (
+ *sc.get<SemanticGraph::Compositor*> (
+ "xsd-frontend-restriction-correspondence"));
+
+ SemanticGraph::Context& bc (b.context ());
+
+ if (b.max () != 1)
+ {
+ sc.set ("s:next", bc.get<String> ("s:next"));
+
+ // Add the *_present callback if this is a restriction
+ // of sequence to optional.
+ //
+ if (s.min () == 0)
+ sc.set ("s:present",
+ find_name (L"sequence", L"_present", set_));
+ }
+ else if (b.min () == 0)
+ sc.set ("s:present", bc.get<String> ("s:present"));
+ }
+ }
+
+ Traversal::Sequence::traverse (s);
+ }
+
+ private:
+ NameSet& set_;
+ Boolean restriction_;
+
+ ParticleTag particle_tag_;
+ Traversal::ContainsParticle contain_particle_tag_;
+ };
+
+ struct SecondaryParticle: Traversal::Element,
+ Traversal::Any,
+ Context
+ {
+ SecondaryParticle (Context& c, NameSet& set, Boolean restriction)
+ : Context (c), set_ (set), restriction_ (restriction)
+ {
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Element& e)
+ {
+ Boolean poly (
+ polymorphic && !e.type ().context ().count ("anonymous"));
+
+ SemanticGraph::Context& ec (e.context ());
+
+ if (!restriction_)
+ {
+ UnsignedLong min (e.min ()), max (e.max ());
+
+ String const& base (ec.get<String> ("s:name"));
+
+ if (min == 0 && max == 1)
+ ec.set ("s:present", find_name (base + L"_present", set_));
+ else if (max != 1)
+ ec.set ("s:next", find_name (base + L"_next", set_));
+
+ ec.set ("s:serializer", find_name (base + L"_serializer", set_));
+ ec.set ("s:member", find_name (base + L"_serializer_", set_));
+
+ if (poly)
+ ec.set ("s:member-map",
+ find_name (base + L"_serializer_map_", set_));
+ }
+ else
+ {
+ SemanticGraph::Element& b (
+ *ec.get<SemanticGraph::Element*> (
+ "xsd-frontend-restriction-correspondence"));
+
+ SemanticGraph::Context& bc (b.context ());
+ UnsignedLong min (b.min ()), max (b.max ());
+
+ if (min == 0 && max == 1)
+ ec.set ("s:present", bc.get<String> ("s:present"));
+ else if (max != 1)
+ {
+ ec.set ("s:next", bc.get<String> ("s:next"));
+
+ // Add the *_present callback if this is a restriction
+ // of sequence to optional.
+ //
+ if (e.min () == 0)
+ {
+ String const& base (bc.get<String> ("s:name"));
+ ec.set ("s:present", find_name (base + L"_present", set_));
+ }
+ }
+
+ ec.set ("s:serializer", bc.get<String> ("s:serializer"));
+ ec.set ("s:member", bc.get<String> ("s:member"));
+
+ if (poly)
+ ec.set ("s:member-map", bc.get<String> ("s:member-map"));
+ }
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Any& a)
+ {
+ using SemanticGraph::Any;
+
+ SemanticGraph::Context& ac (a.context ());
+
+ if (!restriction_)
+ {
+ UnsignedLong min (a.min ()), max (a.max ());
+ String const& base (ac.get<String> ("s:name"));
+
+ if (min == 0 && max == 1)
+ {
+ ac.set ("s:present", find_name (base + L"_present", set_));
+ }
+ else if (max != 1)
+ {
+ ac.set ("s:next", find_name (base + L"_next", set_));
+ }
+
+ ac.set ("s:serialize", find_name (L"serialize_" + base, set_));
+ }
+ else
+ {
+ Any& b (
+ *ac.get<Any*> ("xsd-frontend-restriction-correspondence"));
+
+ SemanticGraph::Context& bc (b.context ());
+ UnsignedLong min (b.min ()), max (b.max ());
+
+ if (min == 0 && max == 1)
+ {
+ ac.set ("s:present", bc.get<String> ("s:present"));
+ }
+ else if (max != 1)
+ {
+ ac.set ("s:next", bc.get<String> ("s:next"));
+
+ // Add the *_present callback if this is a restriction
+ // of sequence to optional.
+ //
+ if (a.min () == 0)
+ {
+ String const& base (bc.get<String> ("s:name"));
+ ac.set ("s:present", find_name (base + L"_present", set_));
+ }
+ }
+
+ ac.set ("s:serialize", bc.get<String> ("s:serialize"));
+ }
+ }
+
+ private:
+ NameSet& set_;
+ Boolean restriction_;
+ };
+
+ struct SecondaryAttribute: Traversal::Attribute,
+ Traversal::AnyAttribute,
+ Context
+ {
+ SecondaryAttribute (Context& c, NameSet& set, Boolean restriction)
+ : Context (c), set_ (set), restriction_ (restriction)
+ {
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Attribute& a)
+ {
+ using SemanticGraph::Attribute;
+
+ SemanticGraph::Context& ac (a.context ());
+
+ if (!restriction_)
+ {
+ String const& base (ac.get<String> ("s:name"));
+
+ if (a.optional ())
+ ac.set ("s:present", find_name (base + L"_present", set_));
+
+ ac.set ("s:serializer", find_name (base + L"_serializer", set_));
+ ac.set ("s:member", find_name (base + L"_serializer_", set_));
+ }
+ else
+ {
+ Attribute& b (
+ *ac.get<Attribute*> ("xsd-frontend-restriction-correspondence"));
+ SemanticGraph::Context& bc (b.context ());
+
+ if (a.optional ())
+ ac.set ("s:present", bc.get<String> ("s:present"));
+
+ ac.set ("s:serializer", bc.get<String> ("s:serializer"));
+ ac.set ("s:member", bc.get<String> ("s:member"));
+ }
+ }
+
+ virtual Void
+ traverse (SemanticGraph::AnyAttribute& a)
+ {
+ using SemanticGraph::AnyAttribute;
+
+ SemanticGraph::Context& ac (a.context ());
+
+ if (!restriction_)
+ {
+ String const& base (ac.get<String> ("s:name"));
+
+ ac.set ("s:next", find_name (base + L"_next", set_));
+ ac.set ("s:serialize", find_name (L"serialize_" + base, set_));
+ }
+ else
+ {
+ AnyAttribute& b (
+ *ac.get<AnyAttribute*> (
+ "xsd-frontend-restriction-correspondence"));
+ SemanticGraph::Context& bc (b.context ());
+
+ ac.set ("s:next", bc.get<String> ("s:next"));
+ ac.set ("s:serialize", bc.get<String> ("s:serialize"));
+ }
+ }
+
+ private:
+ NameSet& set_;
+ Boolean restriction_;
+ };
+
+ //
+ //
+ struct Complex: Traversal::Complex, Context
+ {
+ Complex (Context& c)
+ : Context (c)
+ {
+ }
+
+ virtual Void
+ traverse (Type& c)
+ {
+ SemanticGraph::Context& cc (c.context ());
+
+ // Use processed name.
+ //
+ String const& name (cc.get<String> ("s:name"));
+
+ // We leave this set around to allow other mappings to use
+ // this information.
+ //
+ cc.set ("cxx-serializer-name-processor-member-set", NameSet ());
+ NameSet& member_set (
+ cc.get<NameSet> ("cxx-serializer-name-processor-member-set"));
+
+ member_set.insert (name);
+
+ // Add our base's members to the initial list unless we are
+ // inheriting by restriction in which case we need to have
+ // the same names as our base.
+ //
+ Boolean restriction (false);
+
+ if (c.inherits_p ())
+ {
+ // @@ What if this types name is the same as one of base's
+ // members?
+ //
+ SemanticGraph::Type& base (c.inherits ().base ());
+
+ if (base.is_a<SemanticGraph::Complex> ())
+ {
+ if (!base.context ().count (
+ "cxx-serializer-name-processor-member-set"))
+ {
+ dispatch (base);
+ }
+
+ NameSet const& base_set (
+ base.context ().get<NameSet> (
+ "cxx-serializer-name-processor-member-set"));
+
+ member_set.insert (base_set.begin (), base_set.end ());
+
+ // Inheritance by restriction from anyType is a special case.
+ //
+ restriction = c.inherits ().is_a<SemanticGraph::Restricts> () &&
+ !c.inherits ().base ().is_a<SemanticGraph::AnyType> ();
+ }
+ }
+
+ // First assign the "primary" names.
+ //
+ {
+ if (c.contains_compositor_p ())
+ {
+ PrimaryParticle particle (*this, member_set, restriction);
+ Traversal::Compositor compositor;
+ Traversal::ContainsCompositor contains_compositor;
+ Traversal::ContainsParticle contains_particle;
+
+ contains_compositor >> compositor >> contains_particle;
+
+ contains_particle >> compositor;
+ contains_particle >> particle;
+
+ Complex::contains_compositor (c, contains_compositor);
+ }
+
+ //
+ //
+ PrimaryAttribute attribute (*this, member_set, restriction);
+ Traversal::Names names (attribute);
+
+ Complex::names (c, names);
+ }
+
+ // Assign "secondary" names.
+ //
+ {
+ if (c.contains_compositor_p ())
+ {
+ SecondaryParticle particle (*this, member_set, restriction);
+ SecondaryCompositor compositor (*this, member_set, restriction);
+ Traversal::ContainsCompositor contains_compositor;
+ Traversal::ContainsParticle contains_particle;
+
+ contains_compositor >> compositor >> contains_particle;
+
+ contains_particle >> compositor;
+ contains_particle >> particle;
+
+ Complex::contains_compositor (c, contains_compositor);
+ }
+
+ //
+ //
+ SecondaryAttribute attribute (*this, member_set, restriction);
+ Traversal::Names names (attribute);
+
+ Complex::names (c, names);
+ }
+ }
+ };
+
+
+ //
+ //
+ struct GlobalType: Traversal::Type, Context
+ {
+ GlobalType (Context& c, NameSet& set)
+ : Context (c), set_ (set)
+ {
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Type& t)
+ {
+ String const& n (t.name ());
+ SemanticGraph::Context& tc (t.context ());
+
+ String name (find_name (n + skel_suffix, set_));
+ tc.set ("s:name", name);
+
+ if (tiein)
+ tc.set ("s:tiein", escape (n + L"_impl_"));
+
+ // Note that we do not add this name to the set so that it
+ // does not influence other names.
+ //
+ if (impl)
+ tc.set ("s:impl", escape (n + impl_suffix));
+ }
+
+ private:
+ NameSet& set_;
+ };
+
+
+ struct Namespace: Traversal::Namespace, Context
+ {
+ Namespace (Context& c)
+ : Context (c)
+ {
+ }
+
+ virtual Void
+ traverse (Type& ns)
+ {
+ SemanticGraph::Context& nsc (ns.context ());
+ String const& name (ns.name ());
+
+ // Use a name set associated with this namespace if present.
+ // This will make sure that we don't get any conflicts in the
+ // multi-mapping translation case. Note that here we assume
+ // that all mappings traverse schemas in the same order which
+ // is currently the case.
+ //
+ if (global_type_names.find (name) == global_type_names.end ())
+ {
+ if (!nsc.count ("name-set"))
+ nsc.set ("name-set", NameSet ());
+
+ NameSet& s (nsc.get<NameSet> ("name-set"));
+ global_type_names[name] = &s;
+ }
+
+ NameSet& type_set (*global_type_names[name]);
+
+ GlobalType type (*this, type_set);
+ Traversal::Names names (type);
+
+ Traversal::Namespace::names (ns, names);
+ }
+ };
+
+ struct FundType : Traversal::AnyType,
+ Traversal::AnySimpleType,
+
+ Traversal::Fundamental::Byte,
+ Traversal::Fundamental::UnsignedByte,
+ Traversal::Fundamental::Short,
+ Traversal::Fundamental::UnsignedShort,
+ Traversal::Fundamental::Int,
+ Traversal::Fundamental::UnsignedInt,
+ Traversal::Fundamental::Long,
+ Traversal::Fundamental::UnsignedLong,
+ Traversal::Fundamental::Integer,
+ Traversal::Fundamental::NonPositiveInteger,
+ Traversal::Fundamental::NonNegativeInteger,
+ Traversal::Fundamental::PositiveInteger,
+ Traversal::Fundamental::NegativeInteger,
+
+ Traversal::Fundamental::Boolean,
+
+ Traversal::Fundamental::Float,
+ Traversal::Fundamental::Double,
+ Traversal::Fundamental::Decimal,
+
+ Traversal::Fundamental::String,
+ Traversal::Fundamental::NormalizedString,
+ Traversal::Fundamental::Token,
+ Traversal::Fundamental::Name,
+ Traversal::Fundamental::NameToken,
+ Traversal::Fundamental::NameTokens,
+ Traversal::Fundamental::NCName,
+ Traversal::Fundamental::Language,
+
+ Traversal::Fundamental::QName,
+
+ Traversal::Fundamental::Id,
+ Traversal::Fundamental::IdRef,
+ Traversal::Fundamental::IdRefs,
+
+ Traversal::Fundamental::AnyURI,
+
+ Traversal::Fundamental::Base64Binary,
+ Traversal::Fundamental::HexBinary,
+
+ Traversal::Fundamental::Date,
+ Traversal::Fundamental::DateTime,
+ Traversal::Fundamental::Duration,
+ Traversal::Fundamental::Day,
+ Traversal::Fundamental::Month,
+ Traversal::Fundamental::MonthDay,
+ Traversal::Fundamental::Year,
+ Traversal::Fundamental::YearMonth,
+ Traversal::Fundamental::Time,
+
+ Traversal::Fundamental::Entity,
+ Traversal::Fundamental::Entities,
+
+ Context
+
+ {
+ FundType (Context& c)
+ : Context (c)
+ {
+ }
+
+ // anyType & anySimpleType.
+ //
+ virtual Void
+ traverse (SemanticGraph::AnyType& t)
+ {
+ set_names (t, "any_type");
+ }
+
+ virtual Void
+ traverse (SemanticGraph::AnySimpleType& t)
+ {
+ set_names (t, "any_simple_type");
+ }
+
+ // Boolean.
+ //
+ virtual Void
+ traverse (SemanticGraph::Fundamental::Boolean& t)
+ {
+ set_names (t, "boolean");
+ }
+
+ // Integral types.
+ //
+ virtual Void
+ traverse (SemanticGraph::Fundamental::Byte& t)
+ {
+ set_names (t, "byte");
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::UnsignedByte& t)
+ {
+ set_names (t, "unsigned_byte");
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::Short& t)
+ {
+ set_names (t, "short");
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::UnsignedShort& t)
+ {
+ set_names (t, "unsigned_short");
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::Int& t)
+ {
+ set_names (t, "int");
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::UnsignedInt& t)
+ {
+ set_names (t, "unsigned_int");
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::Long& t)
+ {
+ set_names (t, "long");
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::UnsignedLong& t)
+ {
+ set_names (t, "unsigned_long");
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::Integer& t)
+ {
+ set_names (t, "integer");
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::NonPositiveInteger& t)
+ {
+ set_names (t, "non_positive_integer");
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::NonNegativeInteger& t)
+ {
+ set_names (t, "non_negative_integer");
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::PositiveInteger& t)
+ {
+ set_names (t, "positive_integer");
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::NegativeInteger& t)
+ {
+ set_names (t, "negative_integer");
+ }
+
+ // Floats.
+ //
+ virtual Void
+ traverse (SemanticGraph::Fundamental::Float& t)
+ {
+ set_names (t, "float");
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::Double& t)
+ {
+ set_names (t, "double");
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::Decimal& t)
+ {
+ set_names (t, "decimal");
+ }
+
+ // Strings.
+ //
+ virtual Void
+ traverse (SemanticGraph::Fundamental::String& t)
+ {
+ set_names (t, "string");
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::NormalizedString& t)
+ {
+ set_names (t, "normalized_string");
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::Token& t)
+ {
+ set_names (t, "token");
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::NameToken& t)
+ {
+ set_names (t, "nmtoken");
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::NameTokens& t)
+ {
+ set_names (t, "nmtokens");
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::Name& t)
+ {
+ set_names (t, "name");
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::NCName& t)
+ {
+ set_names (t, "ncname");
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::Language& t)
+ {
+ set_names (t, "language");
+ }
+
+
+ // Qualified name.
+ //
+ virtual Void
+ traverse (SemanticGraph::Fundamental::QName& t)
+ {
+ set_names (t, "qname");
+ }
+
+
+ // ID/IDREF.
+ //
+ virtual Void
+ traverse (SemanticGraph::Fundamental::Id& t)
+ {
+ set_names (t, "id");
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::IdRef& t)
+ {
+ set_names (t, "idref");
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::IdRefs& t)
+ {
+ set_names (t, "idrefs");
+ }
+
+ // URI.
+ //
+ virtual Void
+ traverse (SemanticGraph::Fundamental::AnyURI& t)
+ {
+ set_names (t, "uri");
+ }
+
+ // Binary.
+ //
+ virtual Void
+ traverse (SemanticGraph::Fundamental::Base64Binary& t)
+ {
+ set_names (t, "base64_binary");
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::HexBinary& t)
+ {
+ set_names (t, "hex_binary");
+ }
+
+
+ // Date/time.
+ //
+ virtual Void
+ traverse (SemanticGraph::Fundamental::Date& t)
+ {
+ set_names (t, "date");
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::DateTime& t)
+ {
+ set_names (t, "date_time");
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::Duration& t)
+ {
+ set_names (t, "duration");
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::Day& t)
+ {
+ set_names (t, "gday");
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::Month& t)
+ {
+ set_names (t, "gmonth");
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::MonthDay& t)
+ {
+ set_names (t, "gmonth_day");
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::Year& t)
+ {
+ set_names (t, "gyear");
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::YearMonth& t)
+ {
+ set_names (t, "gyear_month");
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::Time& t)
+ {
+ set_names (t, "time");
+ }
+
+ // Entity.
+ //
+ virtual Void
+ traverse (SemanticGraph::Fundamental::Entity& t)
+ {
+ set_names (t, "entity");
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::Entities& t)
+ {
+ set_names (t, "entities");
+ }
+
+ private:
+ String
+ make_skel_name (String const& base)
+ {
+ return escape (base + skel_suffix);
+ }
+
+ String
+ make_impl_name (String const& base)
+ {
+ return escape (base + impl_suffix);
+ }
+
+ Void
+ set_names (SemanticGraph::Type& t, String const& name)
+ {
+ SemanticGraph::Context& c (t.context ());
+
+ WideChar const* ns = validation
+ ? L"::xsde::cxx::serializer::validating::"
+ : L"::xsde::cxx::serializer::non_validating::";
+
+ String skel (make_skel_name (name));
+ c.set ("s:name", skel);
+ c.set ("s:real-name", ns + skel);
+
+ String impl (make_impl_name (name));
+ c.set ("s:impl", impl);
+ c.set ("s:real-impl", ns + impl);
+
+ c.set ("s:post", L"post_" + name);
+
+ if (tiein)
+ c.set ("s:tiein", name + L"_impl_");
+ }
+ };
+
+ // 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
+ {
+ virtual Void
+ traverse (SemanticGraph::Sources& sr)
+ {
+ SemanticGraph::Schema& s (sr.schema ());
+
+ if (!s.context ().count ("cxx-serializer-name-processor-seen"))
+ {
+ s.context ().set ("cxx-serializer-name-processor-seen", true);
+ Traversal::Sources::traverse (sr);
+ }
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Includes& i)
+ {
+ SemanticGraph::Schema& s (i.schema ());
+
+ if (!s.context ().count ("cxx-serializer-name-processor-seen"))
+ {
+ s.context ().set ("cxx-serializer-name-processor-seen", true);
+ Traversal::Includes::traverse (i);
+ }
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Imports& i)
+ {
+ SemanticGraph::Schema& s (i.schema ());
+
+ if (!s.context ().count ("cxx-serializer-name-processor-seen"))
+ {
+ s.context ().set ("cxx-serializer-name-processor-seen", true);
+ Traversal::Imports::traverse (i);
+ }
+ }
+ };
+
+ // Go into implied schemas while making sure we don't process
+ // the same stuff more than once.
+ //
+ struct Implies: Traversal::Implies
+ {
+ virtual Void
+ traverse (SemanticGraph::Implies& i)
+ {
+ SemanticGraph::Schema& s (i.schema ());
+
+ if (!s.context ().count ("cxx-serializer-name-processor-seen"))
+ {
+ s.context ().set ("cxx-serializer-name-processor-seen", true);
+ Traversal::Implies::traverse (i);
+ }
+ }
+ };
+
+ Void
+ process_impl (CLI::Options const& ops,
+ SemanticGraph::Schema& tu,
+ SemanticGraph::Path const& file)
+ {
+ Context ctx (ops, tu, file);
+
+ if (tu.names_begin ()->named ().name () ==
+ L"http://www.w3.org/2001/XMLSchema")
+ {
+ // XML Schema namespace.
+ //
+ Traversal::Schema schema;
+
+ Traversal::Names schema_names;
+ Traversal::Namespace ns;
+ Traversal::Names ns_names;
+ FundType fund_type (ctx);
+
+ schema >> schema_names >> ns >> ns_names >> fund_type;
+
+ schema.dispatch (tu);
+ }
+ else
+ {
+ // Pass one - assign names to fundamental types.
+ //
+ {
+ Traversal::Schema schema;
+ Implies implies;
+ Traversal::Schema xs_schema;
+
+ schema >> implies >> xs_schema;
+
+ Traversal::Names xs_schema_names;
+ Traversal::Namespace ns;
+ Traversal::Names ns_names;
+ FundType fund_type (ctx);
+
+ xs_schema >> xs_schema_names >> ns >> ns_names >> fund_type;
+
+ schema.dispatch (tu);
+ }
+
+ // Pass two - assign names to global types. This pass cannot
+ // be combined with pass three because of possible recursive
+ // schema inclusions. Also 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 ("cxx-serializer-name-processor-seen"))
+ {
+ Traversal::Schema schema;
+ Uses uses;
+
+ schema >> uses >> schema;
+
+ Traversal::Names schema_names;
+ Namespace ns (ctx);
+
+ schema >> schema_names >> ns;
+
+ // Some twisted schemas do recusive self-inclusion.
+ //
+ tu.context ().set ("cxx-serializer-name-processor-seen", true);
+
+ schema.dispatch (tu);
+ }
+
+ // Pass three - assign names inside complex types. Here we don't
+ // need to go into included/imported schemas.
+ //
+ {
+ Traversal::Schema schema;
+ Traversal::Sources sources;
+
+ schema >> sources >> schema;
+
+ Traversal::Names schema_names;
+ Traversal::Namespace ns;
+ Traversal::Names ns_names;
+
+ schema >> schema_names >> ns >> ns_names;
+
+ Complex complex (ctx);
+
+ ns_names >> complex;
+
+ schema.dispatch (tu);
+ }
+ }
+ }
+ }
+
+ Void NameProcessor::
+ process (CLI::Options const& ops,
+ SemanticGraph::Schema& tu,
+ SemanticGraph::Path const& file)
+ {
+ process_impl (ops, tu, file);
+ }
+ }
+}
diff --git a/xsde/cxx/serializer/name-processor.hxx b/xsde/cxx/serializer/name-processor.hxx
new file mode 100644
index 0000000..bf69ba6
--- /dev/null
+++ b/xsde/cxx/serializer/name-processor.hxx
@@ -0,0 +1,32 @@
+// file : xsde/cxx/serializer/name-processor.hxx
+// author : Boris Kolpackov <boris@codesynthesis.com>
+// copyright : Copyright (c) 2006-2009 Code Synthesis Tools CC
+// license : GNU GPL v2 + exceptions; see accompanying LICENSE file
+
+#ifndef CXX_SERIALIZER_NAME_PROCESSOR_HXX
+#define CXX_SERIALIZER_NAME_PROCESSOR_HXX
+
+#include <cult/types.hxx>
+
+#include <xsd-frontend/semantic-graph.hxx>
+
+#include <cxx/serializer/cli.hxx>
+
+namespace CXX
+{
+ namespace Serializer
+ {
+ using namespace Cult::Types;
+
+ class NameProcessor
+ {
+ public:
+ Void
+ process (CLI::Options const& options,
+ XSDFrontend::SemanticGraph::Schema&,
+ XSDFrontend::SemanticGraph::Path const& file);
+ };
+ }
+}
+
+#endif // CXX_SERIALIZER_NAME_PROCESSOR_HXX
diff --git a/xsde/cxx/serializer/serializer-forward.cxx b/xsde/cxx/serializer/serializer-forward.cxx
new file mode 100644
index 0000000..60d5ce5
--- /dev/null
+++ b/xsde/cxx/serializer/serializer-forward.cxx
@@ -0,0 +1,112 @@
+// file : xsde/cxx/serializer/serializer-forward.cxx
+// author : Boris Kolpackov <boris@codesynthesis.com>
+// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC
+// license : GNU GPL v2 + exceptions; see accompanying LICENSE file
+
+#include <cxx/serializer/serializer-forward.hxx>
+
+#include <xsd-frontend/semantic-graph.hxx>
+#include <xsd-frontend/traversal.hxx>
+
+namespace CXX
+{
+ namespace Serializer
+ {
+ namespace
+ {
+ struct Enumeration: Traversal::Enumeration, Context
+ {
+ Enumeration (Context& c)
+ : Context (c)
+ {
+ }
+
+ virtual Void
+ traverse (Type& e)
+ {
+ os << "class " << ename (e) << ";";
+ }
+ };
+
+ //
+ //
+ struct List: Traversal::List, Context
+ {
+ List (Context& c)
+ : Context (c)
+ {
+ }
+
+ virtual Void
+ traverse (Type& l)
+ {
+ os << "class " << ename (l) << ";";
+ }
+ };
+
+ //
+ //
+ struct Union: Traversal::Union, Context
+ {
+ Union (Context& c)
+ : Context (c)
+ {
+ }
+
+ virtual Void
+ traverse (Type& u)
+ {
+ os << "class " << ename (u) << ";";
+ }
+ };
+
+ //
+ //
+ struct Complex : Traversal::Complex, Context
+ {
+ Complex (Context& c)
+ : Context (c)
+ {
+ }
+
+ virtual Void
+ traverse (Type& c)
+ {
+ os << "class " << ename (c) << ";";
+ }
+ };
+ }
+
+ Void
+ generate_serializer_forward (Context& ctx)
+ {
+ ctx.os << "// Forward declarations" << endl
+ << "//" << endl;
+
+ Traversal::Schema schema;
+
+ Traversal::Sources sources;
+ Traversal::Names schema_names;
+
+ Namespace ns (ctx);
+ Traversal::Names names;
+
+ schema >> sources >> schema;
+ schema >> schema_names >> ns >> names;
+
+ List list (ctx);
+ Union union_ (ctx);
+ Complex complex (ctx);
+ Enumeration enumeration (ctx);
+
+ names >> list;
+ names >> union_;
+ names >> complex;
+ names >> enumeration;
+
+ schema.dispatch (ctx.schema_root);
+
+ ctx.os << endl;
+ }
+ }
+}
diff --git a/xsde/cxx/serializer/serializer-forward.hxx b/xsde/cxx/serializer/serializer-forward.hxx
new file mode 100644
index 0000000..239d82f
--- /dev/null
+++ b/xsde/cxx/serializer/serializer-forward.hxx
@@ -0,0 +1,22 @@
+// file : xsde/cxx/serializer/serializer-forward.hxx
+// author : Boris Kolpackov <boris@codesynthesis.com>
+// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC
+// license : GNU GPL v2 + exceptions; see accompanying LICENSE file
+
+#ifndef CXX_SERIALIZER_SERIALIZER_FORWARD_HXX
+#define CXX_SERIALIZER_SERIALIZER_FORWARD_HXX
+
+#include <xsd-frontend/semantic-graph/schema.hxx>
+
+#include <cxx/serializer/elements.hxx>
+
+namespace CXX
+{
+ namespace Serializer
+ {
+ Void
+ generate_serializer_forward (Context&);
+ }
+}
+
+#endif // CXX_SERIALIZER_SERIALIZER_FORWARD_HXX
diff --git a/xsde/cxx/serializer/serializer-header.cxx b/xsde/cxx/serializer/serializer-header.cxx
new file mode 100644
index 0000000..6ba57f1
--- /dev/null
+++ b/xsde/cxx/serializer/serializer-header.cxx
@@ -0,0 +1,2006 @@
+// file : xsde/cxx/serializer/serializer-header.cxx
+// author : Boris Kolpackov <boris@codesynthesis.com>
+// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC
+// license : GNU GPL v2 + exceptions; see accompanying LICENSE file
+
+#include <cxx/serializer/serializer-header.hxx>
+
+#include <xsd-frontend/semantic-graph.hxx>
+#include <xsd-frontend/traversal.hxx>
+
+namespace CXX
+{
+ namespace Serializer
+ {
+ namespace
+ {
+ // Override classes override pure virtual functions in the base.
+ // Should be in sync with declaration generators below. Used in
+ // tiein implementation.
+ //
+
+ struct CompositorCallbackOverride: Traversal::Choice,
+ Traversal::Sequence,
+ Context
+ {
+ CompositorCallbackOverride (Context& c)
+ : Context (c)
+ {
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Choice& c)
+ {
+ if (c.contains_begin () != c.contains_end ())
+ {
+ UnsignedLong min (c.min ()), max (c.max ());
+
+ if (max != 1 && min != 0)
+ {
+ os << "virtual bool" << endl
+ << enext (c) << " ();"
+ << endl;
+ }
+
+ if (min != 0)
+ {
+ os << "virtual " << earm_tag (c) << endl
+ << earm (c) << " ();"
+ << endl;
+ }
+
+ Traversal::Choice::traverse (c);
+ }
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Sequence& s)
+ {
+ UnsignedLong min (s.min ()), max (s.max ());
+
+ if (max != 1 && min != 0)
+ {
+ os << "virtual bool" << endl
+ << enext (s) << " ();"
+ << endl;
+ }
+
+ Traversal::Sequence::traverse (s);
+ }
+ };
+
+ struct ParticleCallbackOverride: Traversal::Element,
+ Traversal::Any,
+ Context
+ {
+ ParticleCallbackOverride (Context& c)
+ : Context (c)
+ {
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Element& e)
+ {
+ UnsignedLong min (e.min ()), max (e.max ());
+
+ if (max != 1 && min != 0)
+ {
+ os << "virtual bool" << endl
+ << enext (e) << " ();"
+ << endl;
+ }
+
+ String const& ret (ret_type (e.type ()));
+
+ if (ret != L"void")
+ {
+ os << "virtual " << ret << endl
+ << ename (e) << " ();"
+ << endl;
+ }
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Any& a)
+ {
+ UnsignedLong min (a.min ()), max (a.max ());
+
+ if (min != 0 &&
+ !a.contained_particle ().compositor ().is_a<
+ SemanticGraph::Choice> ())
+ {
+ if (max != 1)
+ {
+ os << "virtual bool" << endl
+ << enext (a) << " ();"
+ << endl;
+ }
+
+ if (stl)
+ {
+ os << "virtual void" << endl
+ << ename (a) << " (::std::string& ns, ::std::string& name);"
+ << endl;
+ }
+ else
+ {
+ os << "virtual void" << endl
+ << ename (a) << " (const char*& ns, const char*& name, " <<
+ "bool& free);"
+ << endl;
+ }
+
+ os << "virtual void" << endl
+ << eserialize (a) << " ();"
+ << endl;
+ }
+ }
+ };
+
+ struct AttributeCallbackOverride: Traversal::Attribute, Context
+ {
+ AttributeCallbackOverride (Context& c)
+ : Context (c)
+ {
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Attribute& a)
+ {
+ String const& ret (ret_type (a.type ()));
+
+ if (ret != L"void")
+ {
+ os << "virtual " << ret << endl
+ << ename (a) << " ();"
+ << endl;
+ }
+ }
+ };
+
+ struct BaseOverride: Traversal::Type,
+ Traversal::Enumeration,
+ Traversal::List,
+ Traversal::Union,
+ Traversal::Complex,
+ Context
+ {
+ BaseOverride (Context& c)
+ : Context (c),
+ compositor_callback_ (c),
+ particle_callback_ (c),
+ attribute_callback_ (c)
+ {
+ contains_compositor_callback_ >> compositor_callback_;
+ compositor_callback_ >> contains_particle_callback_;
+ contains_particle_callback_ >> compositor_callback_;
+ contains_particle_callback_ >> particle_callback_;
+
+ names_attribute_callback_ >> attribute_callback_;
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Type& t)
+ {
+ // pre
+ //
+ String const& arg (arg_type (t));
+
+ if (arg != L"void")
+ {
+ os << "virtual void" << endl
+ << "pre (" << arg << ");"
+ << endl;
+ }
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Enumeration& e)
+ {
+ SemanticGraph::Type& t (e);
+ traverse (t);
+ }
+
+ virtual Void
+ traverse (SemanticGraph::List& l)
+ {
+ SemanticGraph::Type& t (l);
+ traverse (t);
+
+ // item
+ //
+ String const& ret (ret_type (l.argumented ().type ()));
+
+ if (ret != L"void")
+ {
+ os << "virtual " << ret << endl
+ << unclash (ename (l), "item") << " ();"
+ << endl;
+ }
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Union& u)
+ {
+ SemanticGraph::Type& t (u);
+ traverse (t);
+
+ // serialize_content
+ //
+ os << "virtual void" << endl
+ << "_serialize_content ();"
+ << endl;
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Complex& c)
+ {
+ SemanticGraph::Type& t (c);
+ traverse (t);
+
+ // Member callbacks.
+ //
+ if (!restriction_p (c))
+ {
+ Traversal::Complex::names (c, names_attribute_callback_);
+ Traversal::Complex::contains_compositor (
+ c, contains_compositor_callback_);
+ }
+ }
+
+ private:
+ CompositorCallbackOverride compositor_callback_;
+ ParticleCallbackOverride particle_callback_;
+ Traversal::ContainsCompositor contains_compositor_callback_;
+ Traversal::ContainsParticle contains_particle_callback_;
+
+ AttributeCallbackOverride attribute_callback_;
+ Traversal::Names names_attribute_callback_;
+ };
+
+ //
+ //
+
+ struct Enumeration: Traversal::Enumeration, Context
+ {
+ Enumeration (Context& c)
+ : Context (c)
+ {
+ }
+
+ virtual Void
+ traverse (Type& e)
+ {
+ String const& name (ename (e));
+ SemanticGraph::Type& base (e.inherits ().base ());
+ String fq_base (fq_name (base));
+
+ os << "class " << name << ": public " <<
+ (mixin ? "virtual " : "") << fq_base
+ << "{"
+ << "public:" << endl
+ << "// Serializer callbacks. Override them in your " <<
+ "implementation." << endl
+ << "//" << endl
+ << endl;
+
+ // pre
+ //
+ String const& arg (arg_type (e));
+ String const& base_arg (arg_type (base));
+
+ if (arg == base_arg)
+ {
+ os << "// virtual void" << endl;
+
+ if (arg == L"void")
+ os << "// pre ();" << endl;
+ else
+ os << "// pre (" << arg << ") = 0;" << endl;
+
+ os << endl;
+ }
+ else
+ {
+ os << "virtual void" << endl;
+
+ if (arg == L"void")
+ os << "pre ();";
+ else
+ os << "pre (" << arg << ") = 0;";
+
+ os << endl;
+ }
+
+ // post
+ //
+ os << "// virtual void" << endl
+ << "// post ();" << endl;
+
+ if (poly_code)
+ {
+ os << endl
+ << "public:" << endl
+ << "static const char*" << endl
+ << "_static_type ();"
+ << endl
+ << "virtual const char*" << endl
+ << "_dynamic_type () const;";
+ }
+
+ if (tiein)
+ {
+ os << endl
+ << "// Constructor." << endl
+ << "//" << endl
+ << name << " (" << fq_base << "* tiein);"
+ << endl;
+
+ os << "// Implementation details." << endl
+ << "//" << endl;
+
+ // If our base has pure virtual functions, override them here.
+ //
+ inherits (e);
+
+ os << "protected:" << endl
+ << name << "* " << etiein (e) << ";"
+ << name << " (" << name << "*, void*);"
+ << endl;
+ }
+
+ os << "};";
+ }
+ };
+
+ //
+ //
+ struct List: Traversal::List, Context
+ {
+ List (Context& c)
+ : Context (c)
+ {
+ }
+
+ virtual Void
+ traverse (Type& l)
+ {
+ String const& name (ename (l));
+ SemanticGraph::Type& t (l.argumented ().type ());
+ String item_type (fq_name (t));
+
+ String item (unclash (name, "item"));
+ String item_next (unclash (name, "item_next"));
+
+ os << "class " << name << ": public " << simple_base
+ << "{"
+ << "public:" << endl
+ << "// Serializer callbacks. Override them in your " <<
+ "implementation." << endl
+ << "//" << endl
+ << endl;
+
+ // pre
+ //
+ String const& arg (arg_type (l));
+
+ os << "virtual void" << endl;
+
+ if (arg == L"void")
+ os << "pre ();";
+ else
+ os << "pre (" << arg << ") = 0;";
+
+ os << endl;
+
+ // item
+ //
+ os << "virtual bool" << endl
+ << item_next << " ();"
+ << endl;
+
+ String const& ret (ret_type (t));
+
+ os << "virtual " << ret << endl
+ << item << " ()" << (ret != L"void" ? " = 0" : "") << ";"
+ << endl;
+
+ // post
+ //
+ os << "// virtual void" << endl
+ << "// post ();" << endl
+ << endl;
+
+ //
+ //
+ os << "// Serializer construction API." << endl
+ << "//" << endl;
+
+ // item_serializer
+ //
+ os << "void" << endl
+ << unclash (name, "item_serializer") << " (" << item_type << "&);"
+ << endl;
+
+ // serializers
+ //
+ os << "void" << endl
+ << "serializers (" << item_type << "& /* item */);"
+ << endl;
+
+ if (reset)
+ os << "virtual void" << endl
+ << "_reset ();"
+ << endl;
+
+ // c-tor
+ //
+ os << "// Constructor." << endl
+ << "//" << endl
+ << name << " ();"
+ << endl;
+
+ if (poly_code)
+ {
+ os << "public:" << endl
+ << "static const char*" << endl
+ << "_static_type ();"
+ << endl
+ << "virtual const char*" << endl
+ << "_dynamic_type () const;"
+ << endl;
+ }
+
+ //
+ //
+ os << "// Implementation." << endl
+ << "//" << endl
+ << "public:" << endl;
+
+ os << "virtual void" << endl
+ << "_serialize_content ();"
+ << endl;
+
+ os << "protected:" << endl;
+
+ if (tiein)
+ {
+ os << name << "* " << etiein (l) << ";"
+ << name << " (" << name << "*, void*);"
+ << endl;
+ }
+
+ os << item_type << "* _xsde_" << item << "_;"
+ << "};";
+ }
+ };
+
+ struct Union: Traversal::Union, Context
+ {
+ Union (Context& c)
+ : Context (c)
+ {
+ }
+
+ virtual Void
+ traverse (Type& u)
+ {
+ String const& name (ename (u));
+
+ os << "class " << name << ": public " << simple_base
+ << "{"
+ << "public:" << endl
+ << "// Serializer callbacks. Override them in your " <<
+ "implementation." << endl
+ << "//" << endl
+ << endl;
+
+ // pre
+ //
+ String const& arg (arg_type (u));
+
+ os << "virtual void" << endl;
+
+ if (arg == L"void")
+ os << "pre ();";
+ else
+ os << "pre (" << arg << ") = 0;";
+
+ os << endl;
+
+ // serialize_content
+ //
+ os << "virtual void" << endl
+ << "_serialize_content () = 0;"
+ << endl;
+
+ // post
+ //
+ os << "// virtual void" << endl
+ << "// post ();" << endl;
+
+ if (poly_code)
+ {
+ os << endl
+ << "public:" << endl
+ << "static const char*" << endl
+ << "_static_type ();"
+ << endl
+ << "virtual const char*" << endl
+ << "_dynamic_type () const;";
+ }
+
+ if (tiein)
+ {
+ // c-tor
+ //
+ os << endl
+ << "// Constructor." << endl
+ << "//" << endl
+ << name << " ();"
+ << endl;
+
+ //
+ //
+ os << "// Implementation details." << endl
+ << "//" << endl
+ << "protected:" << endl
+ << name << "* " << etiein (u) << ";"
+ << name << " (" << name << "*, void*);"
+ << endl;
+ }
+
+ os << "};";
+ }
+ };
+
+ //
+ //
+ struct ParticleTag: Traversal::Particle, Context
+ {
+ ParticleTag (Context& c)
+ : Context (c), first_ (true)
+ {
+ }
+
+ virtual Void
+ traverse (Type& p)
+ {
+ if (first_)
+ first_ = false;
+ else
+ os << "," << endl;
+
+ os << etag (p);
+ }
+
+ private:
+ Boolean first_;
+ };
+
+ struct CompositorCallback: Traversal::All,
+ Traversal::Choice,
+ Traversal::Sequence,
+ Context
+ {
+ CompositorCallback (Context& c)
+ : Context (c)
+ {
+ }
+
+ virtual Void
+ traverse (SemanticGraph::All& a)
+ {
+ if (!a.context ().count ("xsd-frontend-restriction-correspondence"))
+ {
+ // For the all compositor, maxOccurs=1 and minOccurs={0,1}.
+ //
+ if (a.min () == 0)
+ {
+ os << "virtual bool" << endl
+ << epresent (a) << " ();"
+ << endl;
+ }
+ }
+
+ Traversal::All::traverse (a);
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Choice& c)
+ {
+ if (c.contains_begin () != c.contains_end ())
+ {
+ if (SemanticGraph::Compositor* b = correspondent (c))
+ {
+ // Add the *_present callback if this is a restriction
+ // of sequence to optional.
+ //
+ UnsignedLong cmin (c.min ()), bmax (b->max ());
+
+ if (bmax != 1 && cmin == 0)
+ {
+ os << "virtual bool" << endl
+ << epresent (c) << " ();"
+ << endl;
+ }
+ }
+ else
+ {
+ UnsignedLong min (c.min ()), max (c.max ());
+
+ if (min == 0 && max == 1)
+ {
+ os << "virtual bool" << endl
+ << epresent (c) << " ();"
+ << endl;
+ }
+ else if (max != 1)
+ {
+ os << "virtual bool" << endl
+ << enext (c) << " ()" << (min != 0 ? " = 0" : "") << ";"
+ << endl;
+ }
+
+ //
+ //
+ os << "enum " << earm_tag (c)
+ << "{";
+
+ {
+ ParticleTag particle (*this);
+ Traversal::ContainsParticle contain_particle (particle);
+ Traversal::Choice::contains (c, contain_particle);
+ }
+
+ os << "};";
+
+ os << "virtual " << earm_tag (c) << endl
+ << earm (c) << " ()" << (min != 0 ? " = 0" : "") << ";"
+ << endl;
+ }
+
+ Traversal::Choice::traverse (c);
+ }
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Sequence& s)
+ {
+ // Root compositor that models inheritance by extension
+ // may not have an association so we may fall through
+ // in to the 'else' case even though this is a restriction.
+ // This is ok since such a compositor always has max ==
+ // min == 1 and so nothing is generated.
+ //
+ if (SemanticGraph::Compositor* b = correspondent (s))
+ {
+ // Add the *_present callback if this is a restriction
+ // of sequence to optional.
+ //
+ UnsignedLong smin (s.min ());
+ UnsignedLong bmax (b->max ());
+
+ if (bmax != 1 && smin == 0)
+ {
+ os << "virtual bool" << endl
+ << epresent (s) << " ();"
+ << endl;
+ }
+ }
+ else
+ {
+ UnsignedLong min (s.min ()), max (s.max ());
+
+ if (min == 0 && max == 1)
+ {
+ os << "virtual bool" << endl
+ << epresent (s) << " ();"
+ << endl;
+ }
+ else if (max != 1)
+ {
+ os << "virtual bool" << endl
+ << enext (s) << " ()" << (min != 0 ? " = 0" : "") << ";"
+ << endl;
+ }
+ }
+
+ Traversal::Sequence::traverse (s);
+ }
+ };
+
+ struct ParticleCallback: Traversal::Element,
+ Traversal::Any,
+ Context
+ {
+ ParticleCallback (Context& c)
+ : Context (c)
+ {
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Element& e)
+ {
+ if (SemanticGraph::Element* b = correspondent (e))
+ {
+ // Add the *_present callback if this is a restriction
+ // of sequence to optional.
+ //
+ if (b->max () != 1 && e.min () == 0)
+ {
+ os << "virtual bool" << endl
+ << epresent (e) << " ();"
+ << endl;
+ }
+ }
+ else
+ {
+ UnsignedLong min (e.min ()), max (e.max ());
+
+ if (min == 0 && max == 1)
+ {
+ os << "virtual bool" << endl
+ << epresent (e) << " ();"
+ << endl;
+ }
+ else if (max != 1)
+ {
+ os << "virtual bool" << endl
+ << enext (e) << " ()" << (min != 0 ? " = 0" : "") << ";"
+ << endl;
+ }
+
+ String const& ret (ret_type (e.type ()));
+
+ // Make it non-pure-virtual only if the return type is void.
+ //
+ os << "virtual " << ret << endl
+ << ename (e) << " ()" << (ret != L"void" ? " = 0;" : ";")
+ << endl;
+ }
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Any& a)
+ {
+ if (SemanticGraph::Any* b = correspondent (a))
+ {
+ // Add the *_present callback if this is a restriction
+ // of sequence to optional.
+ //
+ if (b->max () != 1 && a.min () == 0)
+ {
+ os << "virtual bool" << endl
+ << epresent (a) << " ();"
+ << endl;
+ }
+ }
+ else
+ {
+ UnsignedLong min (a.min ()), max (a.max ());
+
+ // Generate pure virtual callbacks unless we are optional
+ // or in choice.
+ //
+ Boolean pv (
+ min != 0 &&
+ !a.contained_particle ().compositor ().is_a<
+ SemanticGraph::Choice> ());
+
+ if (min == 0 && max == 1)
+ {
+ os << "virtual bool" << endl
+ << epresent (a) << " ();"
+ << endl;
+ }
+ else if (max != 1)
+ {
+ os << "virtual bool" << endl
+ << enext (a) << " ()" << (pv ? " = 0" : "") << ";"
+ << endl;
+ }
+
+ if (stl)
+ {
+ os << "virtual void" << endl
+ << ename (a) << " (::std::string& ns, ::std::string& name)" <<
+ (pv ? " = 0;" : ";")
+ << endl;
+ }
+ else
+ {
+ os << "virtual void" << endl
+ << ename (a) << " (const char*& ns, const char*& name, " <<
+ "bool& free)" << (pv ? " = 0;" : ";")
+ << endl;
+ }
+
+ os << "virtual void" << endl
+ << eserialize (a) << " ()" << (pv ? " = 0;" : ";")
+ << endl;
+ }
+ }
+ };
+
+ struct AttributeCallback: Traversal::Attribute,
+ Traversal::AnyAttribute,
+ Context
+ {
+ AttributeCallback (Context& c)
+ : Context (c)
+ {
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Attribute& a)
+ {
+ if (a.optional ())
+ {
+ os << "virtual bool" << endl
+ << epresent (a) << " ();"
+ << endl;
+ }
+
+ String const& ret (ret_type (a.type ()));
+
+ // Make it non-pure-virtual only if the return type is void.
+ //
+ os << "virtual " << ret << endl
+ << ename (a) << " ()" << (ret != L"void" ? " = 0;" : ";")
+ << endl;
+ }
+
+ virtual Void
+ traverse (SemanticGraph::AnyAttribute& a)
+ {
+ os << "virtual bool" << endl
+ << enext (a) << " ();"
+ << endl;
+
+ if (stl)
+ {
+ os << "virtual void" << endl
+ << ename (a) << " (::std::string& ns, ::std::string& name);"
+ << endl;
+ }
+ else
+ {
+ os << "virtual void" << endl
+ << ename (a) << " (const char*& ns, const char*& name, " <<
+ "bool& free);"
+ << endl;
+ }
+
+ os << "virtual void" << endl
+ << eserialize (a) << " ();"
+ << endl;
+ }
+ };
+
+
+ //
+ //
+ struct ParticleAccessor: Traversal::Element, Context
+ {
+ ParticleAccessor (Context& c)
+ : Context (c)
+ {
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Element& e)
+ {
+ String const& serializer (eserializer (e));
+
+ os << "void" << endl
+ << serializer << " (" << fq_name (e.type ()) << "&);"
+ << endl;
+
+ if (poly_code && !anonymous (e.type ()))
+ {
+ os << "void" << endl
+ << eserializer (e) << " (" << serializer_map << "&);"
+ << endl;
+ }
+ }
+ };
+
+ struct AttributeAccessor: Traversal::Attribute, Context
+ {
+ AttributeAccessor (Context& c)
+ : Context (c)
+ {
+ }
+
+ virtual Void
+ traverse (Type& a)
+ {
+ os << "void" << endl
+ << eserializer (a) << " (" << fq_name (a.type ()) << "&);"
+ << endl;
+ }
+ };
+
+
+ //
+ //
+ struct ParticleMember: Traversal::Element, Context
+ {
+ ParticleMember (Context& c)
+ : Context (c)
+ {
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Element& e)
+ {
+ String type (fq_name (e.type ()));
+
+ os << type << "* " << emember (e) << ";";
+
+ if (poly_code && !anonymous (e.type ()))
+ {
+ os << serializer_map << "* " << emember_map (e) << ";"
+ << endl;
+ }
+ }
+ };
+
+ struct AttributeMember: Traversal::Attribute, Context
+ {
+ AttributeMember (Context& c)
+ : Context (c)
+ {
+ }
+
+ virtual Void
+ traverse (Type& a)
+ {
+ os << fq_name (a.type ()) << "* " << emember (a) << ";";
+ }
+ };
+
+
+ //
+ //
+ struct Complex : Traversal::Complex, Context
+ {
+ Complex (Context& c)
+ : Context (c),
+ compositor_callback_ (c),
+ particle_callback_ (c),
+ attribute_callback_ (c),
+ particle_accessor_ (c),
+ attribute_accessor_ (c),
+ particle_member_ (c),
+ attribute_member_ (c)
+ {
+ // Callback.
+ //
+ contains_compositor_callback_ >> compositor_callback_;
+ compositor_callback_ >> contains_particle_callback_;
+ contains_particle_callback_ >> compositor_callback_;
+ contains_particle_callback_ >> particle_callback_;
+
+ names_attribute_callback_ >> attribute_callback_;
+
+ // Accessor.
+ //
+ contains_compositor_accessor_ >> compositor_accessor_;
+ compositor_accessor_ >> contains_particle_accessor_;
+ contains_particle_accessor_ >> compositor_accessor_;
+ contains_particle_accessor_ >> particle_accessor_;
+
+ names_attribute_accessor_ >> attribute_accessor_;
+
+ // Member.
+ //
+ contains_compositor_member_ >> compositor_member_;
+ compositor_member_ >> contains_particle_member_;
+ contains_particle_member_ >> compositor_member_;
+ contains_particle_member_ >> particle_member_;
+
+ names_attribute_member_ >> attribute_member_;
+ }
+
+ virtual Void
+ traverse (Type& c)
+ {
+ String const& name (ename (c));
+
+ // In case of an inheritance-by-restriction, we don't need to
+ // generate serializer callbacks, etc. since they are the same
+ // as in the base. We only need the serialization/validation code.
+ //
+ Boolean restriction (restriction_p (c));
+
+ Boolean hb (c.inherits_p ());
+ Boolean he (has<Traversal::Element> (c));
+ Boolean ha (has<Traversal::Attribute> (c));
+
+ Boolean hae (has_particle<Traversal::Any> (c));
+ Boolean haa (has<Traversal::AnyAttribute> (c));
+
+ Boolean hra (false); // Has required attribute.
+ if (ha)
+ {
+ RequiredAttributeTest test (hra);
+ Traversal::Names names_test (test);
+ names (c, names_test);
+ }
+
+ //
+ //
+ os << "class " << name << ": public ";
+
+ if (hb)
+ os << (mixin ? "virtual " : "") << fq_name (c.inherits ().base ());
+ else
+ os << complex_base;
+
+ os << "{"
+ << "public:" << endl
+ << "// Serializer callbacks. Override them in your " <<
+ "implementation." << endl
+ << "//" << endl
+ << endl;
+
+ // pre
+ //
+ String const& arg (arg_type (c));
+ Boolean same (hb && arg == arg_type (c.inherits ().base ()));
+
+ if (same)
+ {
+ os << "// virtual void" << endl;
+
+ if (arg == L"void")
+ os << "// pre ();" << endl;
+ else
+ os << "// pre (" << arg << ") = 0;" << endl;
+
+ os << endl;
+ }
+ else
+ {
+ os << "virtual void" << endl;
+
+ if (arg == L"void")
+ os << "pre ();";
+ else
+ os << "pre (" << arg << ") = 0;";
+
+ os << endl;
+ }
+
+ // Member callbacks.
+ //
+ if (!restriction)
+ {
+ if (ha || haa)
+ {
+ os << "// Attributes." << endl
+ << "//" << endl;
+
+ names (c, names_attribute_callback_);
+ }
+ }
+
+ if (he || hae)
+ {
+ if (!restriction)
+ {
+ os << "// Elements." << endl
+ << "//" << endl;
+ }
+
+ contains_compositor (c, contains_compositor_callback_);
+ }
+
+ // post
+ //
+ os << "// virtual void" << endl
+ << "// post ();" << endl
+ << endl;
+
+ //
+ //
+ if (!restriction && (he || ha))
+ {
+ os << "// Serializer construction API." << endl
+ << "//" << endl;
+
+ os << "void" << endl
+ << "serializers (";
+
+ {
+ SerializerParamDecl decl (*this, false);
+ decl.traverse (c);
+ }
+
+ os << ");"
+ << endl;
+
+ if (ha)
+ {
+ os << "// Individual attribute serializers." << endl
+ << "//" << endl;
+
+ names (c, names_attribute_accessor_);
+ }
+
+ if (he)
+ {
+ os << "// Individual element serializers." << endl
+ << "//" << endl;
+
+ contains_compositor (c, contains_compositor_accessor_);
+ }
+ }
+
+ if (!restriction && (he || ha) && reset)
+ {
+ os << "virtual void" << endl
+ << "_reset ();"
+ << endl;
+ }
+
+ // Default c-tor.
+ //
+ if (tiein || (!restriction && (he || ha)))
+ {
+ os << "// Constructor." << endl
+ << "//" << endl;
+
+ if (hb && tiein)
+ os << name << " (" << fq_name (c.inherits ().base ()) <<
+ "* tiein);"
+ << endl;
+ else
+ os << name << " ();"
+ << endl;
+ }
+
+ if (poly_code)
+ {
+ os << "public:" << endl
+ << "static const char*" << endl
+ << "_static_type ();"
+ << endl
+ << "virtual const char*" << endl
+ << "_dynamic_type () const;"
+ << endl;
+ }
+
+ // Implementation.
+ //
+ if (tiein || he || ha || hae || haa)
+ {
+ os << "// Implementation." << endl
+ << "//" << endl
+ << "public:" << endl;
+
+ // If our base has pure virtual functions, override them here.
+ //
+ if (tiein && hb)
+ inherits (c);
+
+ if (ha || haa)
+ {
+ os << "virtual void" << endl
+ << "_serialize_attributes ();"
+ << endl;
+ }
+
+ if (he || hae)
+ {
+ os << "virtual void" << endl
+ << "_serialize_content ();"
+ << endl;
+ }
+ }
+
+ if (tiein)
+ {
+ os << "protected:" << endl
+ << name << "* " << etiein (c) << ";"
+ << name << " (" << name << "*, void*);"
+ << endl;
+ }
+
+ if (!restriction && (he || ha))
+ {
+ os << "protected:" << endl;
+
+ if (ha)
+ names (c, names_attribute_member_);
+
+ if (he)
+ contains_compositor (c, contains_compositor_member_);
+ }
+
+ os << "};";
+ }
+
+ private:
+ //
+ //
+ CompositorCallback compositor_callback_;
+ ParticleCallback particle_callback_;
+ Traversal::ContainsCompositor contains_compositor_callback_;
+ Traversal::ContainsParticle contains_particle_callback_;
+
+ AttributeCallback attribute_callback_;
+ Traversal::Names names_attribute_callback_;
+
+ //
+ //
+ Traversal::Compositor compositor_accessor_;
+ ParticleAccessor particle_accessor_;
+ Traversal::ContainsCompositor contains_compositor_accessor_;
+ Traversal::ContainsParticle contains_particle_accessor_;
+
+ AttributeAccessor attribute_accessor_;
+ Traversal::Names names_attribute_accessor_;
+
+ //
+ //
+ Traversal::Compositor compositor_member_;
+ ParticleMember particle_member_;
+ Traversal::ContainsCompositor contains_compositor_member_;
+ Traversal::ContainsParticle contains_particle_member_;
+
+ AttributeMember attribute_member_;
+ Traversal::Names names_attribute_member_;
+ };
+
+ struct FundType : Context,
+ Traversal::AnyType,
+ Traversal::AnySimpleType,
+
+ Traversal::Fundamental::Byte,
+ Traversal::Fundamental::UnsignedByte,
+ Traversal::Fundamental::Short,
+ Traversal::Fundamental::UnsignedShort,
+ Traversal::Fundamental::Int,
+ Traversal::Fundamental::UnsignedInt,
+ Traversal::Fundamental::Long,
+ Traversal::Fundamental::UnsignedLong,
+ Traversal::Fundamental::Integer,
+ Traversal::Fundamental::NonPositiveInteger,
+ Traversal::Fundamental::NonNegativeInteger,
+ Traversal::Fundamental::PositiveInteger,
+ Traversal::Fundamental::NegativeInteger,
+
+ Traversal::Fundamental::Boolean,
+ Traversal::Fundamental::Float,
+ Traversal::Fundamental::Double,
+ Traversal::Fundamental::Decimal,
+
+ Traversal::Fundamental::String,
+ Traversal::Fundamental::NormalizedString,
+ Traversal::Fundamental::Token,
+ Traversal::Fundamental::Name,
+ Traversal::Fundamental::NameToken,
+ Traversal::Fundamental::NameTokens,
+ Traversal::Fundamental::NCName,
+ Traversal::Fundamental::Language,
+
+ Traversal::Fundamental::QName,
+
+ Traversal::Fundamental::Id,
+ Traversal::Fundamental::IdRef,
+ Traversal::Fundamental::IdRefs,
+
+ Traversal::Fundamental::AnyURI,
+
+ Traversal::Fundamental::Base64Binary,
+ Traversal::Fundamental::HexBinary,
+
+ Traversal::Fundamental::Date,
+ Traversal::Fundamental::DateTime,
+ Traversal::Fundamental::Duration,
+ Traversal::Fundamental::Day,
+ Traversal::Fundamental::Month,
+ Traversal::Fundamental::MonthDay,
+ Traversal::Fundamental::Year,
+ Traversal::Fundamental::YearMonth,
+ Traversal::Fundamental::Time,
+
+ Traversal::Fundamental::Entity,
+ Traversal::Fundamental::Entities
+ {
+ FundType (Context& c)
+ : Context (c), xs_ns_ (xs_ns_name ())
+ {
+ impl_ns_ = "::xsde::cxx::serializer::";
+ impl_ns_ += (validation ? L"validating" : L"non_validating");
+
+ if (options.value<CLI::no_stl> ())
+ {
+ qname_type_ = L"const " + xs_ns_ + L"::qname*";
+ string_type_ = L"const char*";
+ }
+ else
+ {
+ qname_type_ = xs_ns_ + L"::qname";
+ string_type_ = L"::std::string";
+ }
+
+ string_seq_type_ = L"const " + xs_ns_ + L"::string_sequence*";
+ buffer_type_ = L"const " + xs_ns_ + L"::buffer*";
+
+ if (options.value<CLI::no_long_long> ())
+ {
+ long_type_ = L"long";
+ unsigned_long_type_ = L"unsigned long";
+ }
+ else
+ {
+ long_type_ = L"long long";
+ unsigned_long_type_ = L"unsigned long long";
+ }
+ }
+
+ // anyType & anySimpleType.
+ //
+ virtual Void
+ traverse (SemanticGraph::AnyType& t)
+ {
+ gen_typedef (t, "void");
+ }
+
+ virtual Void
+ traverse (SemanticGraph::AnySimpleType& t)
+ {
+ gen_typedef (t, "void");
+ }
+
+ // Boolean.
+ //
+ virtual Void
+ traverse (SemanticGraph::Fundamental::Boolean& t)
+ {
+ gen_typedef (t, "bool");
+ }
+
+ // Integral types.
+ //
+ virtual Void
+ traverse (SemanticGraph::Fundamental::Byte& t)
+ {
+ gen_typedef (t, "signed char");
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::UnsignedByte& t)
+ {
+ gen_typedef (t, "unsigned char");
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::Short& t)
+ {
+ gen_typedef (t, "short");
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::UnsignedShort& t)
+ {
+ gen_typedef (t, "unsigned short");
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::Int& t)
+ {
+ gen_typedef (t, "int");
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::UnsignedInt& t)
+ {
+ gen_typedef (t, "unsigned int");
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::Long& t)
+ {
+ gen_typedef (t, long_type_);
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::UnsignedLong& t)
+ {
+ gen_typedef (t, unsigned_long_type_);
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::Integer& t)
+ {
+ gen_typedef (t, "long");
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::NegativeInteger& t)
+ {
+ gen_typedef (t, "long");
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::NonPositiveInteger& t)
+ {
+ gen_typedef (t, "long");
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::PositiveInteger& t)
+ {
+ gen_typedef (t, "unsigned long");
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::NonNegativeInteger& t)
+ {
+ gen_typedef (t, "unsigned long");
+ }
+
+ // Floats.
+ //
+ virtual Void
+ traverse (SemanticGraph::Fundamental::Float& t)
+ {
+ gen_typedef (t, "float");
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::Double& t)
+ {
+ gen_typedef (t, "double");
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::Decimal& t)
+ {
+ gen_typedef (t, "double");
+ }
+
+ // Strings.
+ //
+ virtual Void
+ traverse (SemanticGraph::Fundamental::String& t)
+ {
+ gen_typedef (t, string_type_);
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::NormalizedString& t)
+ {
+ gen_typedef (t, string_type_);
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::Token& t)
+ {
+ gen_typedef (t, string_type_);
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::NameToken& t)
+ {
+ nmtoken_ = gen_typedef (t, string_type_);
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::NameTokens& t)
+ {
+ // NMTOKENS uses NMTOKEN implementation to serialize individual
+ // items. As a result, we don't generate NMTOKENS if we didn't
+ // generate NMTOKEN. Here we assume NMTOKEN is handled before
+ // NMTOKENS.
+ //
+ if(nmtoken_)
+ gen_typedef (t, string_seq_type_);
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::Name& t)
+ {
+ gen_typedef (t, string_type_);
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::NCName& t)
+ {
+ gen_typedef (t, string_type_);
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::Language& t)
+ {
+ gen_typedef (t, string_type_);
+ }
+
+ // Qualified name.
+ //
+ virtual Void
+ traverse (SemanticGraph::Fundamental::QName& t)
+ {
+ gen_typedef (t, qname_type_);
+ }
+
+ // ID/IDREF.
+ //
+ virtual Void
+ traverse (SemanticGraph::Fundamental::Id& t)
+ {
+ gen_typedef (t, string_type_);
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::IdRef& t)
+ {
+ idref_ = gen_typedef (t, string_type_);
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::IdRefs& t)
+ {
+ // IDREFS uses IDREF implementation to serialize individual items.
+ // As a result, we don't generate IDREFS if we didn't generate
+ // IDREF. Here we assume IDREF is handled before IDREFS.
+ //
+ if (idref_)
+ gen_typedef (t, string_seq_type_);
+ }
+
+ // URI.
+ //
+ virtual Void
+ traverse (SemanticGraph::Fundamental::AnyURI& t)
+ {
+ gen_typedef (t, string_type_);
+ }
+
+ // Binary.
+ //
+ virtual Void
+ traverse (SemanticGraph::Fundamental::Base64Binary& t)
+ {
+ gen_typedef (t, buffer_type_);
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::HexBinary& t)
+ {
+ gen_typedef (t, buffer_type_);
+ }
+
+
+ // Date/time.
+ //
+ virtual Void
+ traverse (SemanticGraph::Fundamental::Date& t)
+ {
+ gen_typedef (t, xs_ns_ + L"::date");
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::DateTime& t)
+ {
+ gen_typedef (t, xs_ns_ + L"::date_time");
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::Duration& t)
+ {
+ gen_typedef (t, xs_ns_ + L"::duration");
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::Day& t)
+ {
+ gen_typedef (t, xs_ns_ + L"::gday");
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::Month& t)
+ {
+ gen_typedef (t, xs_ns_ + L"::gmonth");
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::MonthDay& t)
+ {
+ gen_typedef (t, xs_ns_ + L"::gmonth_day");
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::Year& t)
+ {
+ gen_typedef (t, xs_ns_ + L"::gyear");
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::YearMonth& t)
+ {
+ gen_typedef (t, xs_ns_ + L"::gyear_month");
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::Time& t)
+ {
+ gen_typedef (t, xs_ns_ + L"::time");
+ }
+
+ // Entity.
+ //
+ virtual Void
+ traverse (SemanticGraph::Fundamental::Entity&)
+ {
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::Entities&)
+ {
+ }
+
+ private:
+ Boolean
+ gen_typedef (SemanticGraph::Type& t, String const& type)
+ {
+ if (ret_type (t) == type)
+ {
+ SemanticGraph::Context& c (t.context ());
+
+ String const& real_name (c.get<String> ("s:real-name"));
+ String const& name (c.get<String> ("s:name"));
+
+ os << "typedef " << real_name << " " << name << ";";
+
+ String const& real_impl (c.get<String> ("s:real-impl"));
+ String const& impl (c.get<String> ("s:impl"));
+
+ os << "typedef " << real_impl << " " << impl << ";"
+ << endl;
+
+ return true;
+ }
+
+ return false;
+ }
+
+ String xs_ns_;
+ String impl_ns_;
+ String qname_type_;
+ String string_type_;
+ String buffer_type_;
+ String string_seq_type_;
+ String long_type_;
+ String unsigned_long_type_;
+
+ Boolean idref_;
+ Boolean nmtoken_;
+ };
+
+ struct FundNamespace : Namespace, Context
+ {
+ FundNamespace (Context& c)
+ : Namespace (c), Context (c)
+ {
+ }
+
+ void
+ traverse (Type& ns)
+ {
+ pre (ns);
+
+ String impl ("::xsde::cxx::serializer::");
+ impl += (validation ? L"validating" : L"non_validating");
+
+ String const c (char_type);
+
+ os << "// Built-in XML Schema types mapping." << endl
+ << "//" << endl
+ << "using ::xsde::cxx::string_sequence;"
+ << "using ::xsde::cxx::qname;"
+ << "using ::xsde::cxx::buffer;"
+ << "using ::xsde::cxx::time_zone;"
+ << "using ::xsde::cxx::gday;"
+ << "using ::xsde::cxx::gmonth;"
+ << "using ::xsde::cxx::gyear;"
+ << "using ::xsde::cxx::gmonth_day;"
+ << "using ::xsde::cxx::gyear_month;"
+ << "using ::xsde::cxx::date;"
+ << "using ::xsde::cxx::time;"
+ << "using ::xsde::cxx::date_time;"
+ << "using ::xsde::cxx::duration;"
+ << endl;
+
+ os << "// Base serializer skeletons." << endl
+ << "//" << endl
+ << "using ::xsde::cxx::serializer::serializer_base;"
+ << "typedef " << impl << "::empty_content " <<
+ "serializer_empty_content;"
+ << "typedef " << impl << "::simple_content " <<
+ "serializer_simple_content;"
+ << "typedef " << impl << "::complex_content " <<
+ "serializer_complex_content;"
+ << endl;
+
+ if (poly_code)
+ {
+ os << "// Serializer map interface and default implementation." << endl
+ << "//" << endl
+ << "using ::xsde::cxx::serializer::serializer_map;"
+ << "using ::xsde::cxx::serializer::serializer_map_impl;"
+ << endl;
+
+ os << "// Substitution and inheritance hashmaps load querying." << endl
+ << "//" << endl
+ << "using ::xsde::cxx::serializer::serializer_smap_buckets;"
+ << "using ::xsde::cxx::serializer::serializer_smap_elements;"
+ << "using ::xsde::cxx::serializer::serializer_smap_bucket_buckets;"
+ << "using ::xsde::cxx::serializer::serializer_smap_bucket_elements;";
+
+ if (validation)
+ os << "using ::xsde::cxx::serializer::validating::serializer_imap_buckets;"
+ << "using ::xsde::cxx::serializer::validating::serializer_imap_elements;";
+
+ os << endl;
+ }
+
+ os << "// Serializer skeletons and implementations for the" << endl
+ << "// XML Schema built-in types." << endl
+ << "//" << endl;
+
+ names (ns);
+
+ os << "// Error codes." << endl
+ << "//" << endl;
+
+ if (!exceptions)
+ os << "using xsde::cxx::sys_error;";
+
+ os << "typedef xsde::cxx::serializer::genx::xml_error " <<
+ "serializer_xml_error;";
+
+ if (validation)
+ os << "typedef xsde::cxx::schema_error " <<
+ "serializer_schema_error;";
+
+ os << endl;
+
+ if (exceptions)
+ {
+ os << "// Exceptions." << endl
+ << "//" << endl
+ << "typedef xsde::cxx::serializer::exception " <<
+ "serializer_exception;"
+ << "typedef xsde::cxx::serializer::xml serializer_xml;";
+
+ if (validation)
+ os << "typedef xsde::cxx::serializer::schema " <<
+ "serializer_schema;";
+
+ os << endl;
+ }
+ else
+ os << "// Error object." << endl
+ << "//" << endl
+ << "typedef xsde::cxx::serializer::error serializer_error;"
+ << endl;
+
+ os << "// Document serializer." << endl
+ << "//" << endl
+ << "using xsde::cxx::serializer::genx::writer;"
+ << "using xsde::cxx::serializer::genx::document_simpl;"
+ << endl;
+
+ os << "// Serializer context." << endl
+ << "//" << endl
+ << "typedef xsde::cxx::serializer::context serializer_context;"
+ << endl;
+
+ post (ns);
+ }
+ };
+ }
+
+ Void
+ generate_serializer_header (Context& ctx, Boolean generate_xml_schema)
+ {
+ NarrowString extern_xml_schema;
+
+ if (!generate_xml_schema)
+ extern_xml_schema = ctx.options.value<CLI::extern_xml_schema> ();
+
+ if (extern_xml_schema)
+ {
+ String name (ctx.hxx_expr->merge (extern_xml_schema));
+
+ ctx.os << "#include " << ctx.process_include_path (name) << endl
+ << endl;
+
+ // Generate includes that came from the type map.
+ //
+ if (ctx.schema_root.context ().count ("s:includes"))
+ {
+ typedef Cult::Containers::Set<String> Includes;
+
+ Includes& is (
+ ctx.schema_root.context ().get<Includes> ("s:includes"));
+
+ for (Includes::ConstReverseIterator i (is.rbegin ());
+ i != is.rend (); ++i)
+ {
+ ctx.os << "#include " << *i << endl;
+ }
+
+ ctx.os << endl;
+ }
+ }
+ else
+ {
+ ctx.os << "#include <xsde/config.h>" << endl
+ << endl;
+
+ // std::string or xsde::cxx::string is used in wildcard API.
+ //
+ if (ctx.stl)
+ {
+ ctx.os << "#include <string>" << endl
+ << endl;
+ }
+ else
+ {
+ ctx.os << "#include <xsde/cxx/string.hxx>" << endl
+ << endl;
+ }
+
+ // Data types.
+ //
+ ctx.os << "#include <xsde/cxx/serializer/xml-schema.hxx>" << endl
+ << endl;
+
+ // Error handling.
+ //
+ if (ctx.exceptions)
+ ctx.os << "#include <xsde/cxx/serializer/exceptions.hxx>" << endl
+ << endl;
+ else
+ {
+ ctx.os << "#include <xsde/cxx/sys-error.hxx>" << endl;
+
+ if (ctx.validation)
+ ctx.os << "#include <xsde/cxx/schema-error.hxx>" << endl;
+
+ ctx.os << "#include <xsde/cxx/serializer/error.hxx>" << endl
+ << "#include <xsde/cxx/serializer/genx/xml-error.hxx>" << endl;
+
+ ctx.os << endl;
+ }
+
+ // Polymorphism support.
+ //
+ if (ctx.poly_code)
+ {
+ ctx.os << "#include <xsde/cxx/serializer/map.hxx>" << endl
+ << "#include <xsde/cxx/serializer/substitution-map-load.hxx>" << endl;
+
+ if (ctx.validation)
+ ctx.os << "#include <xsde/cxx/serializer/validating/inheritance-map-load.hxx>" << endl;
+
+ ctx.os << endl;
+ }
+
+ // Serializers.
+ //
+ if (ctx.validation)
+ ctx.os << "#include <xsde/cxx/serializer/validating/serializer.hxx>" << endl
+ << "#include <xsde/cxx/serializer/validating/xml-schema-sskel.hxx>" << endl
+ << "#include <xsde/cxx/serializer/validating/xml-schema-simpl.hxx>" << endl
+ << endl;
+ else
+ ctx.os << "#include <xsde/cxx/serializer/non-validating/serializer.hxx>" << endl
+ << "#include <xsde/cxx/serializer/non-validating/xml-schema-sskel.hxx>" << endl
+ << "#include <xsde/cxx/serializer/non-validating/xml-schema-simpl.hxx>" << endl
+ << endl;
+
+ // Document.
+ //
+ ctx.os << "#include <xsde/cxx/serializer/genx/document.hxx>" << endl
+ << endl;
+
+ // Generate includes that came from the type map.
+ //
+ if (ctx.schema_root.context ().count ("s:includes"))
+ {
+ typedef Cult::Containers::Set<String> Includes;
+
+ Includes& is (
+ ctx.schema_root.context ().get<Includes> ("s:includes"));
+
+ for (Includes::ConstReverseIterator i (is.rbegin ());
+ i != is.rend (); ++i)
+ {
+ ctx.os << "#include " << *i << endl;
+ }
+
+ ctx.os << endl;
+ }
+
+ // Generate fundamental types.
+ //
+ if (generate_xml_schema)
+ {
+ Traversal::Schema schema;
+ Traversal::Names names;
+ FundNamespace ns (ctx);
+
+ schema >> names >> ns;
+
+ Traversal::Names ns_names;
+ FundType type (ctx);
+
+ ns >> ns_names >> type;
+
+ schema.dispatch (ctx.schema_root);
+ }
+ else
+ {
+ Traversal::Schema schema, xsd;
+ Traversal::Implies implies;
+ Traversal::Names names;
+ FundNamespace ns (ctx);
+
+ schema >> implies >> xsd >> names >> ns;
+
+ Traversal::Names ns_names;
+ FundType type (ctx);
+
+ ns >> ns_names >> type;
+
+ schema.dispatch (ctx.schema_root);
+ }
+ }
+
+ // Generate user type mapping.
+ //
+ if (!generate_xml_schema)
+ {
+ Traversal::Schema schema;
+
+ Traversal::Sources sources;
+ Includes includes (ctx, Includes::header);
+ Traversal::Names schema_names;
+
+ Namespace ns (ctx);
+ Traversal::Names names;
+
+ schema >> includes;
+ schema >> sources >> schema;
+ schema >> schema_names >> ns >> names;
+
+ List list (ctx);
+ Union union_ (ctx);
+ Complex complex (ctx);
+ Enumeration enumeration (ctx);
+
+ names >> list;
+ names >> union_;
+ names >> complex;
+ names >> enumeration;
+
+ BaseOverride base_override (ctx);
+ Traversal::Inherits inherits_override;
+
+ complex >> inherits_override;
+ enumeration >> inherits_override;
+ inherits_override >> base_override;
+
+ schema.dispatch (ctx.schema_root);
+ }
+ }
+ }
+}
diff --git a/xsde/cxx/serializer/serializer-header.hxx b/xsde/cxx/serializer/serializer-header.hxx
new file mode 100644
index 0000000..64c63ab
--- /dev/null
+++ b/xsde/cxx/serializer/serializer-header.hxx
@@ -0,0 +1,22 @@
+// file : xsde/cxx/serializer/serializer-header.hxx
+// author : Boris Kolpackov <boris@codesynthesis.com>
+// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC
+// license : GNU GPL v2 + exceptions; see accompanying LICENSE file
+
+#ifndef CXX_SERIALIZER_SERIALIZER_HEADER_HXX
+#define CXX_SERIALIZER_SERIALIZER_HEADER_HXX
+
+#include <xsd-frontend/semantic-graph/schema.hxx>
+
+#include <cxx/serializer/elements.hxx>
+
+namespace CXX
+{
+ namespace Serializer
+ {
+ Void
+ generate_serializer_header (Context&, Boolean generate_xml_schema);
+ }
+}
+
+#endif // CXX_SERIALIZER_SERIALIZER_HEADER_HXX
diff --git a/xsde/cxx/serializer/serializer-inline.cxx b/xsde/cxx/serializer/serializer-inline.cxx
new file mode 100644
index 0000000..8caa791
--- /dev/null
+++ b/xsde/cxx/serializer/serializer-inline.cxx
@@ -0,0 +1,631 @@
+// file : xsde/cxx/serializer/serializer-inline.cxx
+// author : Boris Kolpackov <boris@codesynthesis.com>
+// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC
+// license : GNU GPL v2 + exceptions; see accompanying LICENSE file
+
+#include <cxx/serializer/serializer-inline.hxx>
+
+#include <xsd-frontend/semantic-graph.hxx>
+#include <xsd-frontend/traversal.hxx>
+
+namespace CXX
+{
+ namespace Serializer
+ {
+ namespace
+ {
+ struct Enumeration: Traversal::Enumeration, Context
+ {
+ Enumeration (Context& c)
+ : Context (c)
+ {
+ }
+
+ virtual Void
+ traverse (Type& e)
+ {
+ if (tiein)
+ {
+ String const& name (ename (e));
+ String const& impl (etiein (e));
+
+ // We have to use "real" (non-typedef) base name in base
+ // initializer because of some broken compilers (EVC 4.0).
+ //
+ SemanticGraph::Type& base (e.inherits ().base ());
+ String fq_base (fq_name (base));
+ String real_fq_base (real_fq_name (base));
+
+ os << "// " << name << endl
+ << "//" << endl
+ << endl;
+
+ os << inl
+ << name << "::" << endl
+ << name << " (" << fq_base << "* tiein)" << endl
+ << ": " << real_fq_base << " (tiein, 0)," << endl
+ << " " << impl << " (0)"
+ << "{"
+ << "}";
+
+ os << inl
+ << name << "::" << endl
+ << name << " (" << name << "* impl, void*)" << endl
+ << ": " << real_fq_base << " (impl, 0)," << endl
+ << " " << impl << " (impl)"
+ << "{"
+ << "}";
+ }
+ }
+ };
+
+
+ //
+ //
+ struct List: Traversal::List, Context
+ {
+ List (Context& c)
+ : Context (c)
+ {
+ }
+
+ virtual Void
+ traverse (Type& l)
+ {
+ String const& name (ename (l));
+ SemanticGraph::Type& t (l.argumented ().type ());
+ String item_type (fq_name (t));
+
+ String item (unclash (name, "item"));
+
+ os << "// " << name << endl
+ << "//" << endl
+ << endl;
+
+ // item_serializer
+ //
+ os << inl
+ << "void " << name << "::" << endl
+ << unclash (name, "item_serializer") << " (" <<
+ item_type << "& " << item << ")"
+ << "{"
+ << "this->_xsde_" << item << "_ = &" << item << ";"
+ << "}";
+
+ // serializers
+ //
+ os << inl
+ << "void " << name << "::" << endl
+ << "serializers (" << item_type << "& " << item << ")"
+ << "{"
+ << "this->_xsde_" << item << "_ = &" << item << ";"
+ << "}";
+
+ // c-tor
+ //
+ os << inl
+ << name << "::" << endl
+ << name << " ()" << endl
+ << ": ";
+
+ if (tiein)
+ os << etiein (l) << " (0)," << endl
+ << " ";
+
+ os << "_xsde_" << item << "_ (0)"
+ << "{"
+ << "}";
+
+ if (tiein)
+ {
+ os << inl
+ << name << "::" << endl
+ << name << " (" << name << "* impl, void*)" << endl
+ << ": " << simple_base << " (impl, 0)," << endl
+ << " " << etiein (l) << " (impl)," << endl
+ << " _xsde_" << item << "_ (0)"
+ << "{"
+ << "}";
+ }
+ }
+ };
+
+ struct Union: Traversal::Union, Context
+ {
+ Union (Context& c)
+ : Context (c)
+ {
+ }
+
+ virtual Void
+ traverse (Type& u)
+ {
+ if (tiein)
+ {
+ String const& name (ename (u));
+ String const& impl (etiein (u));
+
+ os << "// " << name << endl
+ << "//" << endl
+ << endl;
+
+ //
+ //
+ os << inl
+ << name << "::" << endl
+ << name << " ()" << endl
+ << ": " << impl << " (0)"
+ << "{"
+ << "}";
+
+ //
+ //
+ os << inl
+ << name << "::" << endl
+ << name << " (" << name << "* impl, void*)" << endl
+ << ": " << simple_base << " (impl, 0)," << endl
+ << " " << impl << " (impl)"
+ << "{"
+ << "}";
+ }
+ }
+ };
+
+ //
+ //
+ struct ParticleAccessor: Traversal::Element, Context
+ {
+ ParticleAccessor (Context& c)
+ : Context (c)
+ {
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Element& e)
+ {
+ String const& scope (ename (e.scope ()));
+ String const& serializer (eserializer (e));
+
+ os << inl
+ << "void " << scope << "::" << endl
+ << serializer << " (" << fq_name (e.type ()) << "& s)"
+ << "{"
+ << "this->" << emember (e) << " = &s;"
+ << "}";
+
+ if (poly_code && !anonymous (e.type ()))
+ {
+ os << inl
+ << "void " << scope << "::" << endl
+ << serializer << " (" << serializer_map << "& m)"
+ << "{"
+ << "this->" << emember_map (e) << " = &m;"
+ << "}";
+ }
+ }
+ };
+
+ struct AttributeAccessor: Traversal::Attribute, Context
+ {
+ AttributeAccessor (Context& c)
+ : Context (c)
+ {
+ }
+
+ virtual Void
+ traverse (Type& a)
+ {
+ String const& name (ename (a));
+
+ os << inl
+ << "void " << ename (a.scope ()) << "::" << endl
+ << eserializer (a) << " (" << fq_name (a.type ()) << "& " <<
+ name << ")"
+ << "{"
+ << "this->" << emember (a) << " = &" << name << ";"
+ << "}";
+ }
+ };
+
+ //
+ //
+ struct ParticleMemberSet: Traversal::Element, Context
+ {
+ ParticleMemberSet (Context& c)
+ : Context (c)
+ {
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Element& e)
+ {
+ os << "this->" << emember (e) << " = &" << ename (e) << ";";
+ }
+ };
+
+ struct AttributeMemberSet: Traversal::Attribute, Context
+ {
+ AttributeMemberSet (Context& c)
+ : Context (c)
+ {
+ }
+
+ virtual Void
+ traverse (Type& a)
+ {
+ os << "this->" << emember (a) << " = &" << ename (a) << ";";
+ }
+ };
+
+ struct BaseMemberSet: Traversal::Complex,
+ Traversal::List,
+ Context
+ {
+ BaseMemberSet (Context& c)
+ : Context (c)
+ {
+ inherits_ >> *this;
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Complex& c)
+ {
+ inherits (c, inherits_);
+
+ if (!restriction_p (c))
+ {
+ names (c);
+ contains_compositor (c);
+ }
+ }
+
+ virtual Void
+ traverse (SemanticGraph::List& l)
+ {
+ String const& name (ename (l));
+ String item (unclash (name, "item"));
+
+ os << "this->_xsde_" << item << "_ = &" << name << "_item;";
+ }
+
+ private:
+ Traversal::Inherits inherits_;
+ };
+
+ //
+ //
+ struct ParticleMemberInit: Traversal::Element, Context
+ {
+ ParticleMemberInit (Context& c, Boolean comma)
+ : Context (c), first_ (!comma)
+ {
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Element& e)
+ {
+ if (first_)
+ first_ = false;
+ else
+ os << "," << endl << " ";
+
+ os << emember (e) << " (0)";
+
+ if (poly_code && !anonymous (e.type ()))
+ {
+ os << "," << endl
+ << " " << emember_map (e) << " (0)";
+ }
+ }
+
+ private:
+ Boolean first_;
+ };
+
+ struct AttributeMemberInit: Traversal::Attribute, Context
+ {
+ AttributeMemberInit (Context& c, Boolean comma)
+ : Context (c), first_ (!comma)
+ {
+ }
+
+ virtual Void
+ traverse (Type& a)
+ {
+ if (first_)
+ first_ = false;
+ else
+ os << "," << endl << " ";
+
+ os << emember (a) << " (0)";
+ }
+
+ Boolean
+ comma () const
+ {
+ return !first_;
+ }
+
+ private:
+ Boolean first_;
+ };
+
+
+ //
+ //
+ struct Complex: Traversal::Complex, Context
+ {
+ Complex (Context& c)
+ : Context (c),
+ particle_accessor_ (c),
+ attribute_accessor_ (c),
+ base_set_ (c),
+ particle_set_ (c),
+ attribute_set_ (c)
+ {
+ // Accessor.
+ //
+ contains_compositor_accessor_ >> compositor_accessor_;
+ compositor_accessor_ >> contains_particle_accessor_;
+ contains_particle_accessor_ >> compositor_accessor_;
+ contains_particle_accessor_ >> particle_accessor_;
+
+ names_attribute_accessor_ >> attribute_accessor_;
+
+ // Member set.
+ //
+ inherits_base_set_ >> base_set_;
+ base_set_ >> contains_compositor_set_;
+ base_set_ >> names_attribute_set_;
+
+ contains_compositor_set_ >> compositor_set_;
+ compositor_set_ >> contains_particle_set_;
+ contains_particle_set_ >> compositor_set_;
+ contains_particle_set_ >> particle_set_;
+
+ names_attribute_set_ >> attribute_set_;
+ }
+
+ virtual Void
+ traverse (Type& c)
+ {
+ Boolean hb (c.inherits_p ());
+ Boolean he (has<Traversal::Element> (c));
+ Boolean ha (has<Traversal::Attribute> (c));
+ Boolean restriction (restriction_p (c));
+
+ if (!(tiein || (!restriction && (he || ha))))
+ return;
+
+ String const& name (ename (c));
+
+ os << "// " << name << endl
+ << "//" << endl
+ << endl;
+
+ if (!restriction && (he || ha))
+ {
+ // <name>_serializer ()
+ //
+ if (ha)
+ names (c, names_attribute_accessor_);
+
+ if (he)
+ contains_compositor (c, contains_compositor_accessor_);
+
+ // serializer ()
+ //
+
+ os << inl
+ << "void " << name << "::" << endl
+ << "serializers (";
+
+ {
+ SerializerParamDecl decl (*this, true);
+ decl.traverse (c);
+ }
+
+ os << ")"
+ << "{";
+
+ inherits (c, inherits_base_set_);
+
+ if (ha)
+ names (c, names_attribute_set_);
+
+ if (he)
+ contains_compositor (c, contains_compositor_set_);
+
+ os << "}";
+ }
+
+ // We have to use "real" (non-typedef) base name in base
+ // initializer because of some broken compilers (EVC 4.0).
+ //
+ String real_fq_base;
+
+ if (hb && tiein)
+ real_fq_base = real_fq_name (c.inherits ().base ());
+
+ // Default c-tor.
+ //
+ os << inl
+ << name << "::" << endl;
+
+ if (hb && tiein)
+ os << name << " (" << fq_name (c.inherits ().base ()) <<
+ "* tiein)" << endl;
+ else
+ os << name << " ()" << endl;
+
+ os << ": ";
+
+ Boolean comma (false);
+
+ if (hb && tiein)
+ {
+ os << real_fq_base << " (tiein, 0)";
+ comma = true;
+ }
+
+ if (tiein)
+ {
+ if (comma)
+ os << "," << endl << " ";
+
+ os << etiein (c) << " (0)";
+ comma = true;
+ }
+
+ if (!restriction && (he || ha))
+ {
+ if (ha)
+ {
+ AttributeMemberInit attribute_init (*this, comma);
+ Traversal::Names names_attribute_init;
+
+ names_attribute_init >> attribute_init;
+
+ names (c, names_attribute_init);
+
+ comma = attribute_init.comma ();
+ }
+
+ if (he)
+ {
+ Traversal::Compositor compositor_init;
+ ParticleMemberInit particle_init (*this, comma);
+ Traversal::ContainsCompositor contains_compositor_init;
+ Traversal::ContainsParticle contains_particle_init;
+
+ contains_compositor_init >> compositor_init;
+ compositor_init >> contains_particle_init;
+ contains_particle_init >> compositor_init;
+ contains_particle_init >> particle_init;
+
+ contains_compositor (c, contains_compositor_init);
+ }
+ }
+
+ os << "{"
+ << "}";
+
+ // Tiein c-tor.
+ //
+ if (tiein)
+ {
+ os << inl
+ << name << "::" << endl
+ << name << " (" << name << "* impl, void*)" << endl
+ << ": ";
+
+ if (hb)
+ os << real_fq_base << " (impl, 0)," << endl;
+ else
+ os << complex_base << " (impl, 0)," << endl;
+
+ os << " " << etiein (c) << " (impl)";
+
+ Boolean comma (true);
+
+ if (!restriction && (he || ha))
+ {
+ if (ha)
+ {
+ AttributeMemberInit attribute_init (*this, comma);
+ Traversal::Names names_attribute_init;
+
+ names_attribute_init >> attribute_init;
+
+ names (c, names_attribute_init);
+
+ comma = attribute_init.comma ();
+ }
+
+ if (he)
+ {
+ Traversal::Compositor compositor_init;
+ ParticleMemberInit particle_init (*this, comma);
+ Traversal::ContainsCompositor contains_compositor_init;
+ Traversal::ContainsParticle contains_particle_init;
+
+ contains_compositor_init >> compositor_init;
+ compositor_init >> contains_particle_init;
+ contains_particle_init >> compositor_init;
+ contains_particle_init >> particle_init;
+
+ contains_compositor (c, contains_compositor_init);
+ }
+ }
+
+ os << "{"
+ << "}";
+ }
+ }
+
+ private:
+ //
+ //
+ Traversal::Compositor compositor_accessor_;
+ ParticleAccessor particle_accessor_;
+ Traversal::ContainsCompositor contains_compositor_accessor_;
+ Traversal::ContainsParticle contains_particle_accessor_;
+
+ AttributeAccessor attribute_accessor_;
+ Traversal::Names names_attribute_accessor_;
+
+ //
+ //
+ BaseMemberSet base_set_;
+ Traversal::Inherits inherits_base_set_;
+
+ Traversal::Compositor compositor_set_;
+ ParticleMemberSet particle_set_;
+ Traversal::ContainsCompositor contains_compositor_set_;
+ Traversal::ContainsParticle contains_particle_set_;
+
+ AttributeMemberSet attribute_set_;
+ Traversal::Names names_attribute_set_;
+ };
+ }
+
+ Void
+ generate_serializer_inline (Context& ctx)
+ {
+ // Emit "weak" header includes that are used in the file-per-type
+ // compilation model.
+ //
+ if (!ctx.options.value<CLI::generate_inline> ())
+ {
+ Traversal::Schema schema;
+ Includes includes (ctx, Includes::source);
+
+ schema >> includes;
+ schema.dispatch (ctx.schema_root);
+ }
+
+ Traversal::Schema schema;
+
+ Traversal::Sources sources;
+ Traversal::Names schema_names;
+
+ Namespace ns (ctx);
+ Traversal::Names names;
+
+ schema >> sources >> schema;
+ schema >> schema_names >> ns >> names;
+
+ Enumeration enumeration (ctx);
+ List list (ctx);
+ Union union_ (ctx);
+ Complex complex (ctx);
+
+ names >> enumeration;
+ names >> list;
+ names >> union_;
+ names >> complex;
+
+ schema.dispatch (ctx.schema_root);
+ }
+ }
+}
diff --git a/xsde/cxx/serializer/serializer-inline.hxx b/xsde/cxx/serializer/serializer-inline.hxx
new file mode 100644
index 0000000..8cde76d
--- /dev/null
+++ b/xsde/cxx/serializer/serializer-inline.hxx
@@ -0,0 +1,22 @@
+// file : xsde/cxx/serializer/serializer-inline.hxx
+// author : Boris Kolpackov <boris@codesynthesis.com>
+// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC
+// license : GNU GPL v2 + exceptions; see accompanying LICENSE file
+
+#ifndef CXX_SERIALIZER_SERIALIZER_INLINE_HXX
+#define CXX_SERIALIZER_SERIALIZER_INLINE_HXX
+
+#include <xsd-frontend/semantic-graph/schema.hxx>
+
+#include <cxx/serializer/elements.hxx>
+
+namespace CXX
+{
+ namespace Serializer
+ {
+ Void
+ generate_serializer_inline (Context&);
+ }
+}
+
+#endif // CXX_SERIALIZER_SERIALIZER_INLINE_HXX
diff --git a/xsde/cxx/serializer/serializer-source.cxx b/xsde/cxx/serializer/serializer-source.cxx
new file mode 100644
index 0000000..ec30add
--- /dev/null
+++ b/xsde/cxx/serializer/serializer-source.cxx
@@ -0,0 +1,2703 @@
+// file : xsde/cxx/serializer/serializer-source.cxx
+// author : Boris Kolpackov <boris@codesynthesis.com>
+// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC
+// license : GNU GPL v2 + exceptions; see accompanying LICENSE file
+
+#include <cxx/serializer/serializer-source.hxx>
+
+#include <xsd-frontend/semantic-graph.hxx>
+#include <xsd-frontend/traversal.hxx>
+
+namespace CXX
+{
+ namespace Serializer
+ {
+ namespace
+ {
+ // Override classes override pure virtual functions in the base.
+ // Should be in sync with definition generators below. Used in
+ // tiein implementation.
+ //
+
+ struct CompositorCallbackOverride: Traversal::Choice,
+ Traversal::Sequence,
+ Context
+ {
+ CompositorCallbackOverride (Context& c, String const& scope)
+ : Context (c), scope_ (scope)
+ {
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Choice& c)
+ {
+ if (c.contains_begin () != c.contains_end ())
+ {
+ UnsignedLong min (c.min ()), max (c.max ());
+
+ if (min != 0)
+ {
+ SemanticGraph::Type& t (
+ dynamic_cast<SemanticGraph::Type&> (scope (c)));
+
+ String const& impl (etiein (t));
+
+ if (max != 1)
+ {
+ String const& next (enext (c));
+
+ os << "bool " << scope_ << "::" << endl
+ << next << " ()"
+ << "{"
+ << "assert (this->" << impl << ");"
+ << "return this->" << impl << "->" << next << " ();"
+ << "}";
+ }
+
+ String const& arm (earm (c));
+
+ os << fq_name (t) << "::" << earm_tag (c) << " " <<
+ scope_ << "::" << endl
+ << arm << " ()"
+ << "{"
+ << "assert (this->" << impl << ");"
+ << "return this->" << impl << "->" << arm << " ();"
+ << "}";
+ }
+
+ Traversal::Choice::traverse (c);
+ }
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Sequence& s)
+ {
+ UnsignedLong min (s.min ()), max (s.max ());
+
+ if (max != 1 && min != 0)
+ {
+ String const& impl (
+ etiein (dynamic_cast<SemanticGraph::Type&> (scope (s))));
+
+ String const& next (enext (s));
+
+ os << "bool " << scope_ << "::" << endl
+ << next << " ()"
+ << "{"
+ << "assert (this->" << impl << ");"
+ << "return this->" << impl << "->" << next << " ();"
+ << "}";
+ }
+
+ Traversal::Sequence::traverse (s);
+ }
+
+ private:
+ SemanticGraph::Scope&
+ scope (SemanticGraph::Compositor& c)
+ {
+ SemanticGraph::Compositor* root (&c);
+
+ while (root->contained_particle_p ())
+ root = &root->contained_particle ().compositor ();
+
+ return dynamic_cast<SemanticGraph::Scope&> (
+ root->contained_compositor ().container ());
+ }
+
+ private:
+ String const& scope_;
+ };
+
+ struct ParticleCallbackOverride: Traversal::Element,
+ Traversal::Any,
+ Context
+ {
+ ParticleCallbackOverride (Context& c, String const& scope)
+ : Context (c), scope_ (scope)
+ {
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Element& e)
+ {
+ UnsignedLong min (e.min ()), max (e.max ());
+
+ String const& impl (
+ etiein (dynamic_cast<SemanticGraph::Type&> (e.scope ())));
+
+ if (max != 1 && min != 0)
+ {
+ String const& next (enext (e));
+
+ os << "bool " << scope_ << "::" << endl
+ << next << " ()"
+ << "{"
+ << "assert (this->" << impl << ");"
+ << "return this->" << impl << "->" << next << " ();"
+ << "}";
+ }
+
+ String const& ret (ret_type (e.type ()));
+
+ if (ret != L"void")
+ {
+ String const& name (ename (e));
+
+ os << ret << " " << scope_ << "::" << endl
+ << name << " ()"
+ << "{"
+ << "assert (this->" << impl << ");"
+ << "return this->" << impl << "->" << name << " ();"
+ << "}";
+ }
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Any& a)
+ {
+ UnsignedLong min (a.min ()), max (a.max ());
+
+ if (min != 0 &&
+ !a.contained_particle ().compositor ().is_a<
+ SemanticGraph::Choice> ())
+ {
+ String const& impl (
+ etiein (dynamic_cast<SemanticGraph::Type&> (a.scope ())));
+
+ if (max != 1)
+ {
+ String const& next (enext (a));
+
+ os << "bool " << scope_ << "::" << endl
+ << next << " ()"
+ << "{"
+ << "assert (this->" << impl << ");"
+ << "return this->" << impl << "->" << next << " ();"
+ << "}";
+ }
+
+ String const& name (ename (a));
+
+ if (stl)
+ {
+ os << "void " << scope_ << "::" << endl
+ << name << " (::std::string& ns, ::std::string& name)"
+ << "{"
+ << "assert (this->" << impl << ");"
+ << "this->" << impl << "->" << name << " (ns, name);"
+ << "}";
+ }
+ else
+ {
+ os << "void " << scope_ << "::" << endl
+ << name << " (const char*& ns, const char*& name, " <<
+ "bool& free)"
+ << "{"
+ << "assert (this->" << impl << ");"
+ << "this->" << impl << "->" << name << " (ns, name, free);"
+ << "}";
+ }
+
+ String const& serialize (eserialize (a));
+
+ os << "void " << scope_ << "::" << endl
+ << serialize << " ()"
+ << "{"
+ << "assert (this->" << impl << ");"
+ << "this->" << impl << "->" << serialize << " ();"
+ << "}";
+ }
+ }
+
+ private:
+ String const& scope_;
+ };
+
+ struct AttributeCallbackOverride: Traversal::Attribute, Context
+ {
+ AttributeCallbackOverride (Context& c, String const& scope)
+ : Context (c), scope_ (scope)
+ {
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Attribute& a)
+ {
+ String const& ret (ret_type (a.type ()));
+
+ if (ret != L"void")
+ {
+ String const& impl (
+ etiein (dynamic_cast<SemanticGraph::Type&> (a.scope ())));
+
+ String const& name (ename (a));
+
+ os << ret << " " << scope_ << "::" << endl
+ << name << " ()"
+ << "{"
+ << "assert (this->" << impl << ");"
+ << "return this->" << impl << "->" << name << " ();"
+ << "}";
+ }
+ }
+
+ private:
+ String const& scope_;
+ };
+
+ struct BaseOverride: Traversal::Type,
+ Traversal::Enumeration,
+ Traversal::List,
+ Traversal::Union,
+ Traversal::Complex,
+ Context
+ {
+ BaseOverride (Context& c, String const& scope)
+ : Context (c),
+ scope_ (scope),
+ compositor_callback_ (c, scope),
+ particle_callback_ (c, scope),
+ attribute_callback_ (c, scope)
+ {
+ contains_compositor_callback_ >> compositor_callback_;
+ compositor_callback_ >> contains_particle_callback_;
+ contains_particle_callback_ >> compositor_callback_;
+ contains_particle_callback_ >> particle_callback_;
+
+ names_attribute_callback_ >> attribute_callback_;
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Type& t)
+ {
+ // pre
+ //
+ String const& arg (arg_type (t));
+
+ if (arg != L"void")
+ {
+ String const& impl (etiein (t));
+
+ os << "void " << scope_ << "::" << endl
+ << "pre (" << arg << " x)"
+ << "{"
+ << "assert (this->" << impl << ");"
+ << "this->" << impl << "->pre (x);"
+ << "}";
+ }
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Enumeration& e)
+ {
+ SemanticGraph::Type& t (e);
+ traverse (t);
+ }
+
+ virtual Void
+ traverse (SemanticGraph::List& l)
+ {
+ SemanticGraph::Type& t (l);
+ traverse (t);
+
+ // item
+ //
+ String const& ret (ret_type (l.argumented ().type ()));
+
+ if (ret != L"void")
+ {
+ String item (unclash (ename (l), "item"));
+ String const& impl (etiein (l));
+
+ os << ret << " " << scope_ << "::" << endl
+ << item << " ()"
+ << "{"
+ << "assert (this->" << impl << ");"
+ << "return this->" << impl << "->" << item << " ();"
+ << "}";
+ }
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Union& u)
+ {
+ SemanticGraph::Type& t (u);
+ traverse (t);
+
+ // serialize_content
+ //
+ String const& impl (etiein (u));
+
+ os << "void " << scope_ << "::" << endl
+ << "_serialize_content ()"
+ << "{"
+ << "assert (this->" << impl << ");"
+ << "this->" << impl << "->_serialize_content ();"
+ << "}";
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Complex& c)
+ {
+ SemanticGraph::Type& t (c);
+ traverse (t);
+
+ // Member callbacks.
+ //
+ if (!restriction_p (c))
+ {
+ Traversal::Complex::names (c, names_attribute_callback_);
+ Traversal::Complex::contains_compositor (
+ c, contains_compositor_callback_);
+ }
+ }
+
+ private:
+ String const& scope_;
+
+ CompositorCallbackOverride compositor_callback_;
+ ParticleCallbackOverride particle_callback_;
+ Traversal::ContainsCompositor contains_compositor_callback_;
+ Traversal::ContainsParticle contains_particle_callback_;
+
+ AttributeCallbackOverride attribute_callback_;
+ Traversal::Names names_attribute_callback_;
+ };
+
+ //
+ //
+
+ struct Enumeration: Traversal::Enumeration, Context
+ {
+ Enumeration (Context& c)
+ : Context (c)
+ {
+ }
+
+ virtual Void
+ traverse (Type& e)
+ {
+ String const& name (ename (e));
+ String const& arg (arg_type (e));
+ SemanticGraph::Type& base (e.inherits ().base ());
+
+ os << "// " << name << endl
+ << "//" << endl
+ << endl;
+
+ if (arg != arg_type (base) && arg == L"void")
+ {
+ os << "void " << name << "::" << endl
+ << "pre ()"
+ << "{";
+
+ if (tiein)
+ {
+ String const& impl (etiein (e));
+
+ os << "if (this->" << impl << ")" << endl
+ << "this->" << impl << "->pre ();";
+ }
+
+ os << "}";
+ }
+
+ if (poly_code)
+ {
+ String id (e.name ());
+
+ if (String ns = xml_ns_name (e))
+ {
+ id += L' ';
+ id += ns;
+ }
+
+ os << "const char* " << name << "::" << endl
+ << "_static_type ()"
+ << "{"
+ << "return " << strlit (id) << ";"
+ << "}";
+
+ os << "const char* " << name << "::" << endl
+ << "_dynamic_type () const"
+ << "{"
+ << "return _static_type ();"
+ << "}";
+
+ if (validation)
+ {
+ Boolean gen (!anonymous (e));
+
+ // We normally don't need to enter anonymous types into
+ // the inheritance map. The only exception is when an
+ // anonymous types is defined inside an element that
+ // is a member of a substitution group.
+ //
+ if (!gen)
+ {
+ // The first instance that this anonymous type classifies
+ // is the prototype for others if any.
+ //
+ SemanticGraph::Instance& i (
+ e.classifies_begin ()->instance ());
+
+ if (SemanticGraph::Element* e =
+ dynamic_cast<SemanticGraph::Element*> (&i))
+ {
+ if (e->substitutes_p ())
+ gen = true;
+ }
+ }
+
+ if (gen)
+ {
+ os << "static" << endl
+ << "const ::xsde::cxx::serializer::validating::" <<
+ "inheritance_map_entry" << endl
+ << "_xsde_" << name << "_inheritance_map_entry_ (" << endl
+ << name << "::_static_type ()," << endl
+ << fq_name (base) << "::_static_type ());"
+ << endl;
+ }
+ }
+ }
+
+ if (tiein)
+ {
+ // If our base has pure virtual functions, override them here.
+ //
+ BaseOverride t (*this, name);
+ t.dispatch (base);
+ }
+ }
+ };
+
+ //
+ //
+ struct List: Traversal::List, Context
+ {
+ List (Context& c)
+ : Context (c)
+ {
+ }
+
+ virtual Void
+ traverse (Type& l)
+ {
+ String const& name (ename (l));
+ SemanticGraph::Type& t (l.argumented ().type ());
+
+ String const& ret (ret_type (t));
+ String const& arg (arg_type (t));
+
+ String item (unclash (name, "item"));
+ String item_next (unclash (name, "item_next"));
+ String inst (L"_xsde_" + item + L"_");
+
+ os << "// " << name << endl
+ << "//" << endl
+ << endl;
+
+ String impl;
+
+ if (tiein)
+ impl = etiein (l);
+
+ // pre
+ //
+ if (arg_type (l) == L"void")
+ {
+ os << "void " << name << "::" << endl
+ << "pre ()"
+ << "{";
+
+ if (tiein)
+ os << "if (this->" << impl << ")" << endl
+ << "this->" << impl << "->pre ();";
+
+ os << "}";
+ }
+
+ // item
+ //
+ os << "bool " << name << "::" << endl
+ << item_next << " ()"
+ << "{";
+
+ if (tiein)
+ os << "return this->" << impl << " ? this->" << impl << "->" <<
+ item_next << " () : false;";
+ else
+ os << "return false;";
+
+ os << "}";
+
+ if (ret == L"void")
+ {
+ os << ret << " " << name << "::" << endl
+ << item << " ()"
+ << "{";
+
+ if (tiein)
+ os << "if (this->" << impl << ")" << endl
+ << "return this->" << impl << "->" << item << " ();";
+
+ os << "}";
+ }
+
+ // reset
+ //
+ if (reset)
+ {
+ os << "void " << name << "::" << endl
+ << "_reset ()"
+ << "{"
+ << simple_base << "::_reset ();"
+ << endl
+ << "if (this->" << inst << ")" << endl
+ << "this->" << inst << "->_reset ();"
+ << "}";
+ }
+
+ // serialize_content
+ //
+ os << "void " << name << "::" << endl
+ << "_serialize_content ()"
+ << "{";
+
+ os << "bool first = true;"
+ << "::xsde::cxx::serializer::context& ctx = this->_context ();"
+ << endl;
+
+ if (exceptions && !validation)
+ {
+ os << "while (this->" << item_next << " ())"
+ << "{"
+ << "if (this->" << inst << ")"
+ << "{";
+
+ if (ret == L"void")
+ os << "this->" << item << " ();"
+ << "this->" << inst << "->pre ();";
+ else
+ os << arg << " r = this->" << item << " ();"
+ << "this->" << inst << "->pre (r);";
+
+ os << endl
+ << "if (!first)" << endl
+ << "this->_characters (\" \", 1);"
+ << "else" << endl
+ << "first = false;"
+ << endl;
+
+ os << "this->" << inst << "->_pre_impl (ctx);"
+ << "this->" << inst << "->_serialize_content ();"
+ << "this->" << inst << "->_post_impl ();"
+ << "this->" << inst << "->post ();";
+
+ os << "}"
+ << "}";
+ }
+ else
+ {
+ os << "while (this->" << item_next << " ())"
+ << "{"
+ << "if (this->" << inst << ")"
+ << "{";
+
+ if (ret == L"void")
+ os << "this->" << item << " ();";
+ else
+ os << arg << " r = this->" << item << " ();";
+
+ os << endl
+ << "if (ctx.error_type ())" << endl
+ << "break;"
+ << endl;
+
+ if (ret == L"void")
+ os << "this->" << inst << "->pre ();";
+ else
+ os << "this->" << inst << "->pre (r);";
+
+ if (!exceptions)
+ {
+ os << endl
+ << "if (this->" << inst << "->_error_type ())" << endl
+ << "this->" << inst << "->_copy_error (ctx);"
+ << endl;
+
+ os << "if (ctx.error_type ())" << endl
+ << "break;";
+ }
+
+ if (!exceptions)
+ os << endl
+ << "if (!first)"
+ << "{"
+ << "if (!this->_characters (\" \", 1))" << endl
+ << "break;"
+ << "}";
+ else
+ os << endl
+ << "if (!first)" << endl
+ << "this->_characters (\" \", 1);";
+
+ os << "else" << endl
+ << "first = false;"
+ << endl;
+
+ os << "this->" << inst << "->_pre_impl (ctx);";
+
+ os << endl
+ << "if (ctx.error_type ())" << endl
+ << "break;"
+ << endl;
+
+ os << "this->" << inst << "->_serialize_content ();";
+
+ os << endl
+ << "if (ctx.error_type ())" << endl
+ << "break;"
+ << endl;
+
+ os << "this->" << inst << "->_post_impl ();";
+
+ os << endl
+ << "if (ctx.error_type ())" << endl
+ << "break;"
+ << endl;
+
+ os << "this->" << inst << "->post ();";
+
+ if (!exceptions)
+ {
+ os << endl
+ << "if (this->" << inst << "->_error_type ())" << endl
+ << "this->" << inst << "->_copy_error (ctx);"
+ << endl;
+
+ os << "if (ctx.error_type ())" << endl
+ << "break;";
+ }
+
+ os << "}" // No check for error here since we return anyway.
+ << "}";
+ }
+
+ os << "}"; // _serialize_content
+
+ //
+ //
+ if (poly_code)
+ {
+ String id (l.name ());
+
+ if (String ns = xml_ns_name (l))
+ {
+ id += L' ';
+ id += ns;
+ }
+
+ os << "const char* " << name << "::" << endl
+ << "_static_type ()"
+ << "{"
+ << "return " << strlit (id) << ";"
+ << "}";
+
+ os << "const char* " << name << "::" << endl
+ << "_dynamic_type () const"
+ << "{"
+ << "return _static_type ();"
+ << "}";
+ }
+ }
+ };
+
+ //
+ //
+ struct Union: Traversal::Union, Context
+ {
+ Union (Context& c)
+ : Context (c)
+ {
+ }
+
+ virtual Void
+ traverse (Type& u)
+ {
+ String const& name (ename (u));
+ String const& arg (arg_type (u));
+
+ if (arg == L"void" || poly_code)
+ {
+ os << "// " << name << endl
+ << "//" << endl
+ << endl;
+ }
+
+ if (arg == L"void")
+ {
+ os << "void " << name << "::" << endl
+ << "pre ()"
+ << "{";
+
+ if (tiein)
+ {
+ String const& impl (etiein (u));
+
+ os << "if (this->" << impl << ")" << endl
+ << "this->" << impl << "->pre ();";
+ }
+
+ os << "}";
+ }
+
+ if (poly_code)
+ {
+ String id (u.name ());
+
+ if (String ns = xml_ns_name (u))
+ {
+ id += L' ';
+ id += ns;
+ }
+
+ os << "const char* " << name << "::" << endl
+ << "_static_type ()"
+ << "{"
+ << "return " << strlit (id) << ";"
+ << "}";
+
+ os << "const char* " << name << "::" << endl
+ << "_dynamic_type () const"
+ << "{"
+ << "return _static_type ();"
+ << "}";
+ }
+ }
+ };
+
+ //
+ //
+ struct ParticleReset: Traversal::Element, Context
+ {
+ ParticleReset (Context& c)
+ : Context (c)
+ {
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Element& e)
+ {
+ String const& m (emember (e));
+
+ os << "if (this->" << m << ")" << endl
+ << "this->" << m << "->_reset ();"
+ << endl;
+
+ if (poly_code && !anonymous (e.type ()))
+ {
+ String const& map (emember_map (e));
+
+ os << "if (this->" << map << ")" << endl
+ << "this->" << map << "->reset ();"
+ << endl;
+ }
+ }
+ };
+
+ struct AttributeReset: Traversal::Attribute, Context
+ {
+ AttributeReset (Context& c)
+ : Context (c)
+ {
+ }
+
+ virtual Void
+ traverse (Type& a)
+ {
+ String const& m (emember (a));
+
+ os << "if (this->" << m << ")" << endl
+ << "this->" << m << "->_reset ();"
+ << endl;
+ }
+ };
+
+ // Complex serialization code.
+ //
+ struct Compositor: Traversal::All,
+ Traversal::Choice,
+ Traversal::Sequence,
+ Context
+ {
+ Compositor (Context& c)
+ : Context (c)
+ {
+ }
+
+ virtual Void
+ traverse (SemanticGraph::All& a)
+ {
+ // For the all compositor, maxOccurs=1 and minOccurs={0,1}.
+ //
+ UnsignedLong min (a.min ());
+
+ if (min == 0)
+ os << "if (this->" << epresent (a) << " ())"
+ << "{";
+
+ Traversal::All::traverse (a);
+
+ if (min == 0)
+ {
+ os << "}";
+
+ if (!exceptions)
+ {
+ os << "if (ctx.error_type ())" << endl
+ << "return;"
+ << endl;
+ }
+ }
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Choice& c)
+ {
+ if (c.contains_begin () != c.contains_end ())
+ {
+ UnsignedLong min (c.min ()), max (c.max ());
+
+ if (min == 0 && max == 1)
+ {
+ os << "if (this->" << epresent (c) << " ())"
+ << "{";
+ }
+ else if (max != 1)
+ {
+ os << "while (this->" << enext (c) << " ())"
+ << "{";
+ }
+ else if (!exceptions)
+ {
+ os << "{";
+ }
+
+ if (exceptions)
+ os << "switch (this->" << earm (c) << " ())";
+ else
+ os << earm_tag (c) << " t = this->" << earm (c) << " ();"
+ << endl
+ << "if (ctx.error_type ())" << endl
+ << "return;"
+ << endl
+ << "switch (t)";
+
+
+ os << "{";
+
+ for (SemanticGraph::Choice::ContainsIterator
+ i (c.contains_begin ()); i != c.contains_end (); ++i)
+ {
+ os << "case " << etag (i->particle ()) << ":"
+ << "{";
+
+ edge_traverser ().dispatch (*i);
+
+ os << "break;"
+ << "}";
+ }
+
+ // In case of restriction we may not handle all enumerators
+ // in which case default will help avoid warnings.
+ //
+ os << "default:"
+ << "{"
+ << "break;"
+ << "}"
+ << "}"; // switch
+
+ if (min == 0 || max != 1)
+ {
+ os << "}";
+
+ if (!exceptions)
+ {
+ os << "if (ctx.error_type ())" << endl
+ << "return;"
+ << endl;
+ }
+ }
+ else if (!exceptions)
+ {
+ os << "}";
+ }
+ }
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Sequence& s)
+ {
+ UnsignedLong min (s.min ()), max (s.max ());
+
+ if (min == 0 && max == 1)
+ {
+ os << "if (this->" << epresent (s) << " ())"
+ << "{";
+ }
+ else if (max != 1)
+ {
+ os << "while (this->" << enext (s) << " ())"
+ << "{";
+ }
+
+ Traversal::Sequence::traverse (s);
+
+
+ if (min == 0 || max != 1)
+ {
+ os << "}";
+
+ if (!exceptions)
+ {
+ os << "if (ctx.error_type ())" << endl
+ << "return;"
+ << endl;
+ }
+ }
+ }
+ };
+
+ struct Particle: Traversal::Element,
+ Traversal::Any,
+ Context
+ {
+ Particle (Context& c)
+ : Context (c)
+ {
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Element& e)
+ {
+ UnsignedLong min (e.min ()), max (e.max ());
+
+ String const& name (ename (e));
+
+ os << "// " << name << endl
+ << "//" << endl;
+
+ if (min == 0 && max == 1)
+ {
+ os << "if (this->" << epresent (e) << " ())";
+ }
+ else if (max != 1)
+ {
+ os << "while (this->" << enext (e) << " ())";
+ }
+
+ os << "{";
+
+ String const& ret (ret_type (e.type ()));
+ String const& arg (arg_type (e.type ()));
+ String fq_type (fq_name (e.type ()));
+
+ Boolean poly (poly_code && !anonymous (e.type ()));
+ String inst (poly ? String (L"s") : L"this->" + emember (e));
+
+ if (poly)
+ os << "ctx.type_id (0);";
+
+ if (ret == L"void")
+ os << "this->" << name << " ();"
+ << endl;
+ else
+ os << arg << " r = this->" << name << " ();"
+ << endl;
+
+ if (!exceptions)
+ os << "if (ctx.error_type ())" << endl
+ << "return;"
+ << endl;
+
+ if (poly)
+ {
+ // In case of mixin we use virtual inheritance and only
+ // dynamic_cast can be used.
+ //
+ String cast (mixin ? L"dynamic_cast" : L"static_cast");
+
+ os << "const void* t = ctx.type_id ();"
+ << fq_type << "* " << inst << " = 0;"
+ << endl
+ << "if (t == 0 && this->" << emember (e) << " != 0)" << endl
+ << inst << " = this->" << emember (e) << ";"
+ << "else if (this->" << emember_map (e) << " != 0)" << endl
+ << inst << " = " << cast << "< " << fq_type << "* > (" << endl
+ << "this->" << emember_map (e) << "->find (t));"
+ << endl;
+ }
+
+ os << "if (" << inst << ")"
+ << "{";
+
+ if (exceptions)
+ {
+ if (ret == L"void")
+ os << inst << "->pre ();";
+ else
+ os << inst << "->pre (r);";
+
+ if (poly)
+ {
+ os << endl
+ << "const char* dt = 0;"
+ << "if (t != 0)"
+ << "{"
+ << "dt = " << inst << "->_dynamic_type ();"
+ << "if (strcmp (dt, " << fq_type <<
+ "::_static_type ()) == 0)" << endl
+ << "dt = 0;"
+ << "}";
+ }
+
+ // Only a globally-defined element can be a subst-group root.
+ //
+ if (poly && e.global ())
+ {
+ if (e.qualified () && e.namespace_ ().name ())
+ os << "const char* ns = " <<
+ strlit (e.namespace_ ().name ()) << ";";
+ else
+ os << "const char* ns = 0;";
+
+ os << "const char* n = " << strlit (e.name ()) << ";"
+ << endl;
+
+ os << "if (dt != 0 && " <<
+ "::xsde::cxx::serializer::substitution_map_instance ()" <<
+ ".check (ns, n, dt))" << endl
+ << "dt = 0;"
+ << endl;
+
+ os << "if (ns != 0)" << endl
+ << "this->_start_element (ns, n);"
+ << "else" << endl
+ << "this->_start_element (n);";
+ }
+ else
+ {
+ if (e.qualified () && e.namespace_ ().name ())
+ os << "this->_start_element (" <<
+ strlit (e.namespace_ ().name ()) << ", " <<
+ strlit (e.name ()) << ");";
+ else
+ os << "this->_start_element (" << strlit (e.name ()) << ");";
+ }
+
+ if (poly)
+ {
+ // Set xsi:type if necessary.
+ //
+ os << endl
+ << "if (dt != 0)" << endl
+ << "this->_set_type (dt);"
+ << endl;
+ }
+
+ os << inst << "->_pre_impl (ctx);"
+ << inst << "->_serialize_attributes ();"
+ << inst << "->_serialize_content ();"
+ << inst << "->_post_impl ();"
+ << "this->_end_element ();"
+ << inst << "->post ();";
+ }
+ else
+ {
+ if (ret == L"void")
+ os << inst << "->pre ();";
+ else
+ os << inst << "->pre (r);";
+
+ // Note that after pre() we need to check both the serializer
+ // and context error states because of the recursive parsing.
+ //
+ os << endl
+ << "if (" << inst << "->_error_type ())" << endl
+ << inst << "->_copy_error (ctx);"
+ << endl;
+
+ os << "if (ctx.error_type ())" << endl
+ << "return;"
+ << endl;
+
+ if (poly)
+ {
+ os << "const char* dt = 0;"
+ << "if (t != 0)"
+ << "{"
+ << "dt = " << inst << "->_dynamic_type ();"
+ << "if (strcmp (dt, " << fq_type <<
+ "::_static_type ()) == 0)" << endl
+ << "dt = 0;"
+ << "}";
+ }
+
+ // Only a globally-defined element can be a subst-group root.
+ //
+ if (poly && e.global ())
+ {
+ if (e.qualified () && e.namespace_ ().name ())
+ os << "const char* ns = " <<
+ strlit (e.namespace_ ().name ()) << ";";
+ else
+ os << "const char* ns = 0;";
+
+ os << "const char* n = " << strlit (e.name ()) << ";"
+ << endl;
+
+ os << "if (dt != 0 && " <<
+ "::xsde::cxx::serializer::substitution_map_instance ()" <<
+ ".check (ns, n, dt))" << endl
+ << "dt = 0;"
+ << endl;
+
+ os << "if (ns != 0)"
+ << "{"
+ << "if (!this->_start_element (ns, n))" << endl
+ << "return;"
+ << "}"
+ << "else"
+ << "{"
+ << "if (!this->_start_element (n))" << endl
+ << "return;"
+ << "}";
+ }
+ else
+ {
+ if (e.qualified () && e.namespace_ ().name ())
+ os << "if (!this->_start_element (" <<
+ strlit (e.namespace_ ().name ()) << ", " <<
+ strlit (e.name ()) << "))" << endl
+ << "return;"
+ << endl;
+ else
+ os << "if (!this->_start_element (" <<
+ strlit (e.name ()) << "))" << endl
+ << "return;"
+ << endl;
+ }
+
+ if (poly)
+ {
+ // Set xsi:type if necessary.
+ //
+ os << "if (dt != 0)"
+ << "{"
+ << "if (!this->_set_type (dt))" << endl
+ << "return;"
+ << "}";
+ }
+
+ os << inst << "->_pre_impl (ctx);";
+
+ os << endl
+ << "if (ctx.error_type ())" << endl
+ << "return;"
+ << endl;
+
+ os << inst << "->_serialize_attributes ();";
+
+ os << endl
+ << "if (ctx.error_type ())" << endl
+ << "return;"
+ << endl;
+
+ os << inst << "->_serialize_content ();";
+
+ os << endl
+ << "if (ctx.error_type ())" << endl
+ << "return;"
+ << endl;
+
+ os << inst << "->_post_impl ();";
+
+ os << endl
+ << "if (ctx.error_type ())" << endl
+ << "return;"
+ << endl;
+
+ os << "if (!this->_end_element ())" << endl
+ << "return;"
+ << endl;
+
+ os << inst << "->post ();";
+
+ // Note that after post() we need to check both the serializer
+ // and context error states because of the recursive parsing.
+ //
+ os << endl
+ << "if (" << inst << "->_error_type ())" << endl
+ << inst << "->_copy_error (ctx);"
+ << endl;
+
+ os << "if (ctx.error_type ())" << endl
+ << "return;";
+ }
+
+ os << "}" // if (inst)
+ << "}";
+
+ if ((min == 0 || max != 1) && !exceptions)
+ {
+ os << "if (ctx.error_type ())" << endl
+ << "return;"
+ << endl;
+ }
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Any& a)
+ {
+ UnsignedLong min (a.min ()), max (a.max ());
+
+ if (min == 0 && max == 1)
+ {
+ os << "if (this->" << epresent (a) << " ())";
+
+ }
+ else if (max != 1)
+ {
+ os << "while (this->" << enext (a) << " ())";
+ }
+
+ os << "{";
+
+ if (stl)
+ {
+ os << "::std::string ns, name;";
+
+ if (exceptions)
+ {
+ os << "this->" << ename (a) << " (ns, name);"
+ << endl
+ << "if (ns.empty ())" << endl
+ << "this->_start_element (name.c_str ());"
+ << "else" << endl
+ << "this->_start_element (ns.c_str (), name.c_str ());"
+ << endl
+ << "this->" << eserialize (a) << " ();"
+ << "this->_end_element ();";
+ }
+ else
+ {
+ os << "this->" << ename (a) << " (ns, name);"
+ << endl
+ << "if (ctx.error_type ())" << endl
+ << "return;"
+ << endl
+ << "if (ns.empty ())"
+ << "{"
+ << "if (!this->_start_element (name.c_str ()))" << endl
+ << "return;"
+ << "}"
+ << "else"
+ << "{"
+ << "if (!this->_start_element (ns.c_str (), " <<
+ "name.c_str ()))" << endl
+ << "return;"
+ << "}"
+ << "this->" << eserialize (a) << " ();"
+ << endl
+ << "if (ctx.error_type ())" << endl
+ << "return;"
+ << endl
+ << "if (!this->_end_element ())" << endl
+ << "return;";
+ }
+ }
+ else
+ {
+ os << "const char* ns = 0;"
+ << "const char* name;"
+ << "bool free;";
+
+ if (exceptions)
+ {
+ os << "this->" << ename (a) << " (ns, name, free);"
+ << endl
+ << "::xsde::cxx::string auto_ns, auto_name;"
+ << "if (free)"
+ << "{"
+ << "auto_ns.attach (const_cast< char* > (ns));"
+ << "auto_name.attach (const_cast< char* > (name));"
+ << "}"
+ << "if (ns == 0 || *ns == '\\0')" << endl
+ << "this->_start_element (name);"
+ << "else" << endl
+ << "this->_start_element (ns, name);"
+ << endl
+ << "this->" << eserialize (a) << " ();"
+ << "this->_end_element ();";
+ }
+ else
+ {
+ os << "this->" << ename (a) << " (ns, name, free);"
+ << endl
+ << "if (ctx.error_type ())" << endl
+ << "return;"
+ << endl
+ << "bool r;"
+ << "if (ns == 0 || *ns == '\\0')" << endl
+ << "r = this->_start_element (name);"
+ << "else" << endl
+ << "r = this->_start_element (ns, name);"
+ << endl
+ << "if (free)"
+ << "{"
+ << "delete[] ns;"
+ << "delete[] name;"
+ << "}"
+ << "if (!r)" << endl
+ << "return;"
+ << endl
+ << "this->" << eserialize (a) << " ();"
+ << endl
+ << "if (ctx.error_type ())" << endl
+ << "return;"
+ << endl
+ << "if (!this->_end_element ())" << endl
+ << "return;";
+ }
+ }
+
+ os << "}";
+
+ if (!exceptions && (min == 0 || max != 1))
+ {
+ os << "if (ctx.error_type ())" << endl
+ << "return;"
+ << endl;
+ }
+ }
+
+ };
+
+ struct Attribute: Traversal::Attribute,
+ Traversal::AnyAttribute,
+ Context
+ {
+ Attribute (Context& c)
+ : Context (c)
+ {
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Attribute& a)
+ {
+ String const& name (ename (a));
+
+ os << "// " << name << endl
+ << "//" << endl;
+
+ if (a.optional ())
+ {
+ os << "if (this->" << epresent (a) << " ())";
+ }
+
+ os << "{";
+
+ String const& inst (emember (a));
+ String const& ret (ret_type (a.type ()));
+ String const& arg (arg_type (a.type ()));
+
+ if (ret == L"void")
+ os << "this->" << name << " ();"
+ << endl;
+ else
+ os << arg << " r = this->" << name << " ();"
+ << endl;
+
+ if (!exceptions)
+ os << "if (ctx.error_type ())" << endl
+ << "return;"
+ << endl;
+
+ os << "if (this->" << inst << ")"
+ << "{";
+
+ if (exceptions)
+ {
+ if (ret == L"void")
+ os << "this->" << inst << "->pre ();";
+ else
+ os << "this->" << inst << "->pre (r);";
+
+ if (a.qualified () && a.namespace_ ().name ())
+ os << "this->_start_attribute (" <<
+ strlit (a.namespace_ ().name ()) << ", " <<
+ strlit (a.name ()) << ");";
+ else
+ os << "this->_start_attribute (" << strlit (a.name ()) << ");";
+
+ os << "this->" << inst << "->_pre_impl (ctx);"
+ << "this->" << inst << "->_serialize_content ();"
+ << "this->" << inst << "->_post_impl ();"
+ << "this->_end_attribute ();"
+ << "this->" << inst << "->post ();";
+ }
+ else
+ {
+ if (ret == L"void")
+ os << "this->" << inst << "->pre ();";
+ else
+ os << "this->" << inst << "->pre (r);";
+
+ os << endl
+ << "if (this->" << inst << "->_error_type ())" << endl
+ << "this->" << inst << "->_copy_error (ctx);"
+ << endl;
+
+ os << "if (ctx.error_type ())" << endl
+ << "return;"
+ << endl;
+
+ if (a.qualified () && a.namespace_ ().name ())
+ os << "if (!this->_start_attribute (" <<
+ strlit (a.namespace_ ().name ()) << ", " <<
+ strlit (a.name ()) << "))" << endl
+ << "return;"
+ << endl;
+ else
+ os << "if (!this->_start_attribute (" <<
+ strlit (a.name ()) << "))" << endl
+ << "return;"
+ << endl;
+
+ os << "this->" << inst << "->_pre_impl (ctx);";
+
+ os << endl
+ << "if (ctx.error_type ())" << endl
+ << "return;"
+ << endl;
+
+ os << "this->" << inst << "->_serialize_content ();";
+
+ os << endl
+ << "if (ctx.error_type ())" << endl
+ << "return;"
+ << endl;
+
+ os << "this->" << inst << "->_post_impl ();";
+
+ os << endl
+ << "if (ctx.error_type ())" << endl
+ << "return;"
+ << endl;
+
+ os << "if (!this->_end_attribute ())" << endl
+ << "return;"
+ << endl;
+
+ os << "this->" << inst << "->post ();";
+
+ os << endl
+ << "if (this->" << inst << "->_error_type ())" << endl
+ << "this->" << inst << "->_copy_error (ctx);"
+ << endl;
+
+ os << "if (ctx.error_type ())" << endl
+ << "return;";
+ }
+
+ os << "}" // if (inst)
+ << "}";
+
+ if (a.optional () && !exceptions)
+ {
+ os << "if (ctx.error_type ())" << endl
+ << "return;"
+ << endl;
+ }
+ }
+
+ virtual Void
+ traverse (SemanticGraph::AnyAttribute& a)
+ {
+ os << "while (this->" << enext (a) << " ())"
+ << "{";
+
+ if (stl)
+ {
+ os << "::std::string ns, name;";
+
+ if (exceptions)
+ {
+ os << "this->" << ename (a) << " (ns, name);"
+ << endl
+ << "if (ns.empty ())" << endl
+ << "this->_start_attribute (name.c_str ());"
+ << "else" << endl
+ << "this->_start_attribute (ns.c_str (), name.c_str ());"
+ << endl
+ << "this->" << eserialize (a) << " ();"
+ << "this->_end_attribute ();";
+ }
+ else
+ {
+ os << "this->" << ename (a) << " (ns, name);"
+ << endl
+ << "if (ctx.error_type ())" << endl
+ << "return;"
+ << endl
+ << "if (ns.empty ())"
+ << "{"
+ << "if (!this->_start_attribute (name.c_str ()))" << endl
+ << "return;"
+ << "}"
+ << "else"
+ << "{"
+ << "if (!this->_start_attribute (ns.c_str (), " <<
+ "name.c_str ()))" << endl
+ << "return;"
+ << "}"
+ << "this->" << eserialize (a) << " ();"
+ << endl
+ << "if (ctx.error_type ())" << endl
+ << "return;"
+ << endl
+ << "if (!this->_end_attribute ())" << endl
+ << "return;";
+ }
+ }
+ else
+ {
+ os << "const char* ns = 0;"
+ << "const char* name;"
+ << "bool free;";
+
+ if (exceptions)
+ {
+ os << "this->" << ename (a) << " (ns, name, free);"
+ << endl
+ << "::xsde::cxx::string auto_ns, auto_name;"
+ << "if (free)"
+ << "{"
+ << "auto_ns.attach (const_cast< char* > (ns));"
+ << "auto_name.attach (const_cast< char* > (name));"
+ << "}"
+ << "if (ns == 0 || *ns == '\\0')" << endl
+ << "this->_start_attribute (name);"
+ << "else" << endl
+ << "this->_start_attribute (ns, name);"
+ << endl
+ << "this->" << eserialize (a) << " ();"
+ << "this->_end_attribute ();";
+ }
+ else
+ {
+ os << "this->" << ename (a) << " (ns, name, free);"
+ << endl
+ << "if (ctx.error_type ())" << endl
+ << "return;"
+ << endl
+ << "bool r;"
+ << "if (ns == 0 || *ns == '\\0')" << endl
+ << "r = this->_start_attribute (name);"
+ << "else" << endl
+ << "r = this->_start_attribute (ns, name);"
+ << endl
+ << "if (free)"
+ << "{"
+ << "delete[] ns;"
+ << "delete[] name;"
+ << "}"
+ << "if (!r)" << endl
+ << "return;"
+ << endl
+ << "this->" << eserialize (a) << " ();"
+ << endl
+ << "if (ctx.error_type ())" << endl
+ << "return;"
+ << endl
+ << "if (!this->_end_attribute ())" << endl
+ << "return;";
+ }
+ }
+
+ os << "}";
+
+ if (!exceptions)
+ {
+ os << "if (ctx.error_type ())" << endl
+ << "return;"
+ << endl;
+ }
+ }
+ };
+
+ // Callbacks.
+ //
+ struct CompositorCallback: Traversal::All,
+ Traversal::Choice,
+ Traversal::Sequence,
+ Context
+ {
+ CompositorCallback (Context& c)
+ : Context (c)
+ {
+ }
+
+ virtual Void
+ traverse (SemanticGraph::All& a)
+ {
+ if (!a.context ().count ("xsd-frontend-restriction-correspondence"))
+ {
+ // For the all compositor, maxOccurs=1 and minOccurs={0,1}.
+ //
+ if (a.min () == 0)
+ {
+ SemanticGraph::Scope& s (scope (a));
+ String const& present (epresent (a));
+
+ os << "bool " << ename (s) << "::" << endl
+ << present << " ()"
+ << "{";
+
+ if (tiein)
+ {
+ String const& impl (
+ etiein (dynamic_cast<SemanticGraph::Type&> (s)));
+
+ os << "return this->" << impl << " ? this->" << impl <<
+ "->" << present << " () : false;";
+ }
+ else
+ os << "return false;";
+
+ os << "}";
+ }
+ }
+
+ Traversal::All::traverse (a);
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Choice& c)
+ {
+ if (SemanticGraph::Compositor* b = correspondent (c))
+ {
+ UnsignedLong smin (c.min ());
+ UnsignedLong bmax (b->max ());
+
+ if (bmax != 1 && smin == 0)
+ {
+ String const& next (enext (c));
+ String const& present (epresent (c));
+
+ SemanticGraph::Scope& scope (this->scope (c));
+
+ os << "bool " << ename (scope) << "::" << endl
+ << present << " ()"
+ << "{";
+
+ if (tiein)
+ {
+ String const& impl (
+ etiein (dynamic_cast<SemanticGraph::Type&> (scope)));
+
+ os << "return this->" << impl << " ? this->" << impl <<
+ "->" << present << " () : this->" << next << " ();";
+ }
+ else
+ os << "return this->" << next << " ();";
+
+ os << "}";
+ }
+ }
+ else
+ {
+ UnsignedLong min (c.min ()), max (c.max ());
+
+ if (min == 0)
+ {
+ SemanticGraph::Scope& scope (this->scope (c));
+ String const& s (ename (scope));
+
+ String impl;
+
+ if (tiein)
+ impl = etiein (dynamic_cast<SemanticGraph::Type&> (scope));
+
+ if (max == 1)
+ {
+ String const& present (epresent (c));
+
+ os << "bool " << s << "::" << endl
+ << present << " ()"
+ << "{";
+
+ if (tiein)
+ os << "return this->" << impl << " ? this->" << impl <<
+ "->" << present << " () : false;";
+ else
+ os << "return false;";
+
+ os << "}";
+ }
+ else
+ {
+ String const& next (enext (c));
+
+ os << "bool " << s << "::" << endl
+ << next << " ()"
+ << "{";
+
+ if (tiein)
+ os << "return this->" << impl << " ? this->" << impl <<
+ "->" << next << " () : false;";
+ else
+ os << "return false;";
+
+ os << "}";
+ }
+
+ String const& arm (earm (c));
+ String const& tag (etag (c.contains_begin ()->particle ()));
+
+ os << s << "::" << earm_tag (c) << " " << s << "::" << endl
+ << arm << " ()"
+ << "{";
+
+ if (tiein)
+ os << "return this->" << impl << " ? this->" << impl <<
+ "->" << arm << " () : " << tag << ";";
+ else
+ os << "return " << tag << ";";
+
+ os << "}";
+ }
+ }
+
+ Traversal::Choice::traverse (c);
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Sequence& s)
+ {
+ if (SemanticGraph::Compositor* b = correspondent (s))
+ {
+ UnsignedLong smin (s.min ());
+ UnsignedLong bmax (b->max ());
+
+ if (bmax != 1 && smin == 0)
+ {
+ String const& next (enext (s));
+ String const& present (epresent (s));
+
+ SemanticGraph::Scope& scope (this->scope (s));
+
+ os << "bool " << ename (scope) << "::" << endl
+ << present << " ()"
+ << "{";
+
+ if (tiein)
+ {
+ String const& impl (
+ etiein (dynamic_cast<SemanticGraph::Type&> (scope)));
+
+ os << "return this->" << impl << " ? this->" << impl <<
+ "->" << present << " () : this->" << next << " ();";
+ }
+ else
+ os << "return this->" << next << " ();";
+
+ os << "}";
+ }
+ }
+ else
+ {
+ UnsignedLong min (s.min ()), max (s.max ());
+
+ if (min == 0)
+ {
+ SemanticGraph::Scope& scope (this->scope (s));
+
+ String impl;
+
+ if (tiein)
+ impl = etiein (dynamic_cast<SemanticGraph::Type&> (scope));
+
+ if (max == 1)
+ {
+ String const& present (epresent (s));
+
+ os << "bool " << ename (scope) << "::" << endl
+ << present << " ()"
+ << "{";
+
+ if (tiein)
+ os << "return this->" << impl << " ? this->" << impl <<
+ "->" << present << " () : false;";
+ else
+ os << "return false;";
+
+ os << "}";
+ }
+ else
+ {
+ String const& next (enext (s));
+
+ os << "bool " << ename (scope) << "::" << endl
+ << next << " ()"
+ << "{";
+
+ if (tiein)
+ os << "return this->" << impl << " ? this->" << impl <<
+ "->" << next << " () : false;";
+ else
+ os << "return false;";
+
+ os << "}";
+ }
+ }
+ }
+
+ Traversal::Sequence::traverse (s);
+ }
+
+ private:
+ SemanticGraph::Scope&
+ scope (SemanticGraph::Compositor& c)
+ {
+ SemanticGraph::Compositor* root (&c);
+
+ while (root->contained_particle_p ())
+ root = &root->contained_particle ().compositor ();
+
+ return dynamic_cast<SemanticGraph::Scope&> (
+ root->contained_compositor ().container ());
+ }
+ };
+
+ struct ParticleCallback: Traversal::Element,
+ Traversal::Any,
+ Context
+ {
+ ParticleCallback (Context& c)
+ : Context (c)
+ {
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Element& e)
+ {
+ if (SemanticGraph::Element* b = correspondent (e))
+ {
+ if (b->max () != 1 && e.min () == 0)
+ {
+ String const& next (enext (e));
+ String const& present (epresent (e));
+
+ os << "bool " << ename (e.scope ()) << "::" << endl
+ << present << " ()"
+ << "{";
+
+ if (tiein)
+ {
+ String const& impl (
+ etiein (dynamic_cast<SemanticGraph::Type&> (e.scope ())));
+
+ os << "return this->" << impl << " ? this->" << impl <<
+ "->" << present << " () : this->" << next << " ();";
+ }
+ else
+ os << "return this->" << next << " ();";
+
+ os << "}";
+ }
+ }
+ else
+ {
+ UnsignedLong min (e.min ()), max (e.max ());
+ String const& s (ename (e.scope ()));
+
+ String impl;
+
+ if (tiein)
+ impl = etiein (dynamic_cast<SemanticGraph::Type&> (e.scope ()));
+
+ if (min == 0)
+ {
+ if (max == 1)
+ {
+ String const& present (epresent (e));
+
+ os << "bool " << s << "::" << endl
+ << present << " ()"
+ << "{";
+
+ if (tiein)
+ os << "return this->" << impl << " ? this->" << impl <<
+ "->" << present << " () : false;";
+ else
+ os << "return false;";
+
+ os << "}";
+ }
+ else
+ {
+ String const& next (enext (e));
+
+ os << "bool " << s << "::" << endl
+ << next << " ()"
+ << "{";
+
+ if (tiein)
+ os << "return this->" << impl << " ? this->" << impl <<
+ "->" << next << " () : false;";
+ else
+ os << "return false;";
+
+ os << "}";
+ }
+ }
+
+ // The callback is non-pure-virtual only if the return type
+ // is void.
+ //
+ if (ret_type (e.type ()) == L"void")
+ {
+ String const& name (ename (e));
+
+ os << "void " << s << "::" << endl
+ << name << " ()"
+ << "{";
+
+ if (tiein)
+ os << "if (this->" << impl << ")" << endl
+ << "this->" << impl << "->" << name << " ();";
+
+ os << "}";
+ }
+ }
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Any& a)
+ {
+ if (SemanticGraph::Any* b = correspondent (a))
+ {
+ if (b->max () != 1 && a.min () == 0)
+ {
+ String const& next (enext (a));
+ String const& present (epresent (a));
+
+ os << "bool " << ename (a.scope ()) << "::" << endl
+ << present << " ()"
+ << "{";
+
+ if (tiein)
+ {
+ String const& impl (
+ etiein (dynamic_cast<SemanticGraph::Type&> (a.scope ())));
+
+ os << "return this->" << impl << " ? this->" << impl <<
+ "->" << present << " () : this->" << next << " ();";
+ }
+ else
+ os << "return this->" << next << " ();";
+
+ os << "}";
+ }
+ }
+ else
+ {
+ UnsignedLong min (a.min ()), max (a.max ());
+
+ if (min == 0 ||
+ a.contained_particle ().compositor ().is_a<
+ SemanticGraph::Choice> ())
+ {
+ String const& s (ename (a.scope ()));
+ String impl;
+
+ if (tiein)
+ impl = etiein (dynamic_cast<SemanticGraph::Type&> (a.scope ()));
+
+ if (min == 0 && max == 1)
+ {
+ String const& present (epresent (a));
+
+ os << "bool " << s << "::" << endl
+ << present << " ()"
+ << "{";
+
+ if (tiein)
+ os << "return this->" << impl << " ? this->" << impl <<
+ "->" << present << " () : false;";
+ else
+ os << "return false;";
+
+ os << "}";
+ }
+ else if (max != 1)
+ {
+ String const& next (enext (a));
+
+ os << "bool " << s << "::" << endl
+ << next << " ()"
+ << "{";
+
+ if (tiein)
+ os << "return this->" << impl << " ? this->" << impl <<
+ "->" << next << " () : false;";
+ else
+ os << "return false;";
+
+ os << "}";
+ }
+
+ String const& name (ename (a));
+
+ if (stl)
+ {
+ if (tiein)
+ os << "void " << s << "::" << endl
+ << name << " (::std::string& ns, ::std::string& n)"
+ << "{"
+ << "if (this->" << impl << ")" << endl
+ << "this->" << impl << "->" << name << " (ns, n);"
+ << "}";
+
+ else
+ os << "void " << s << "::" << endl
+ << name << " (::std::string&, ::std::string&)"
+ << "{"
+ << "}";
+ }
+ else
+ {
+ if (tiein)
+ os << "void " << s << "::" << endl
+ << name << " (const char*& ns, const char*& n, bool& f)"
+ << "{"
+ << "if (this->" << impl << ")" << endl
+ << "this->" << impl << "->" << name << " (ns, n, f);"
+ << "}";
+ else
+ os << "void " << s << "::" << endl
+ << name << " (const char*&, const char*&, bool&)"
+ << "{"
+ << "}";
+ }
+
+ String const& serialize (eserialize (a));
+
+ os << "void " << s << "::" << endl
+ << serialize << " ()"
+ << "{";
+
+ if (tiein)
+ os << "if (this->" << impl << ")" << endl
+ << "this->" << impl << "->" << serialize << " ();";
+
+ os << "}";
+ }
+ }
+
+ }
+ };
+
+ struct AttributeCallback: Traversal::Attribute,
+ Traversal::AnyAttribute,
+ Context
+ {
+ AttributeCallback (Context& c)
+ : Context (c)
+ {
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Attribute& a)
+ {
+ String const& s (ename (a.scope ()));
+
+ String impl;
+
+ if (tiein)
+ impl = etiein (dynamic_cast<SemanticGraph::Type&> (a.scope ()));
+
+ if (a.optional ())
+ {
+ String const& present (epresent (a));
+
+ os << "bool " << s << "::" << endl
+ << present << " ()"
+ << "{";
+
+ if (tiein)
+ os << "return this->" << impl << " ? this->" << impl <<
+ "->" << present << " () : false;";
+ else
+ os << "return false;";
+
+ os << "}";
+ }
+
+ // The callback is non-pure-virtual only if the return type
+ // is void.
+ //
+ if (ret_type (a.type ()) == L"void")
+ {
+ String const& name (ename (a));
+
+ os << "void " << s << "::" << endl
+ << name << " ()"
+ << "{";
+
+ if (tiein)
+ os << "if (this->" << impl << ")" << endl
+ << "this->" << impl << "->" << name << " ();";
+
+ os << "}";
+ }
+ }
+
+ virtual Void
+ traverse (SemanticGraph::AnyAttribute& a)
+ {
+ String const& s (ename (a.scope ()));
+
+ String impl;
+
+ if (tiein)
+ impl = etiein (dynamic_cast<SemanticGraph::Type&> (a.scope ()));
+
+ String const& next (enext (a));
+
+ os << "bool " << s << "::" << endl
+ << next << " ()"
+ << "{";
+
+ if (tiein)
+ os << "return this->" << impl << " ? this->" << impl <<
+ "->" << next << " () : false;";
+ else
+ os << "return false;";
+
+ os << "}";
+
+ String const& name (ename (a));
+
+ if (stl)
+ {
+ if (tiein)
+ os << "void " << s << "::" << endl
+ << name << " (::std::string& ns, ::std::string& n)"
+ << "{"
+ << "if (this->" << impl << ")" << endl
+ << "this->" << impl << "->" << name << " (ns, n);"
+ << "}";
+
+ else
+ os << "void " << s << "::" << endl
+ << name << " (::std::string&, ::std::string&)"
+ << "{"
+ << "}";
+ }
+ else
+ {
+ if (tiein)
+ os << "void " << s << "::" << endl
+ << name << " (const char*& ns, const char*& n, bool& f)"
+ << "{"
+ << "if (this->" << impl << ")" << endl
+ << "this->" << impl << "->" << name << " (ns, n, f);"
+ << "}";
+ else
+ os << "void " << s << "::" << endl
+ << name << " (const char*&, const char*&, bool&)"
+ << "{"
+ << "}";
+ }
+
+ String const& serialize (eserialize (a));
+
+ os << "void " << s << "::" << endl
+ << serialize << " ()"
+ << "{";
+
+ if (tiein)
+ os << "if (this->" << impl << ")" << endl
+ << "this->" << impl << "->" << serialize << " ();";
+
+ os << "}";
+ }
+ };
+
+ //
+ //
+ struct Complex : Traversal::Complex, Context
+ {
+ Complex (Context& c)
+ : Context (c),
+ compositor_callback_ (c),
+ particle_callback_ (c),
+ attribute_callback_ (c),
+ particle_reset_ (c),
+ attribute_reset_ (c),
+ compositor_ (c),
+ particle_ (c),
+ attribute_ (c)
+ {
+ // Callback.
+ //
+ contains_compositor_callback_ >> compositor_callback_;
+ compositor_callback_ >> contains_particle_callback_;
+ contains_particle_callback_ >> compositor_callback_;
+ contains_particle_callback_ >> particle_callback_;
+
+ names_attribute_callback_ >> attribute_callback_;
+
+ // Reset.
+ //
+ contains_compositor_reset_ >> compositor_reset_;
+ compositor_reset_ >> contains_particle_reset_;
+ contains_particle_reset_ >> compositor_reset_;
+ contains_particle_reset_ >> particle_reset_;
+
+ names_attribute_reset_ >> attribute_reset_;
+
+ // Serialization code.
+ //
+ contains_compositor_ >> compositor_;
+ compositor_ >> contains_particle_;
+ contains_particle_ >> compositor_;
+ contains_particle_ >> particle_;
+
+ names_attribute_ >> attribute_;
+ }
+
+ virtual Void
+ traverse (Type& c)
+ {
+ Boolean hb (c.inherits_p ());
+ Boolean he (has<Traversal::Element> (c));
+ Boolean ha (has<Traversal::Attribute> (c));
+
+ Boolean hae (has_particle<Traversal::Any> (c));
+ Boolean haa (has<Traversal::AnyAttribute> (c));
+
+ String const& arg (arg_type (c));
+ Boolean same (hb && arg == arg_type (c.inherits ().base ()));
+
+ String const& name (ename (c));
+
+ os << "// " << name << endl
+ << "//" << endl
+ << endl;
+
+ // pre
+ //
+ if (!same && arg == L"void")
+ {
+ os << "void " << name << "::" << endl
+ << "pre ()"
+ << "{";
+
+ if (tiein)
+ {
+ String const& impl (etiein (c));
+
+ os << "if (this->" << impl << ")" << endl
+ << "this->" << impl << "->pre ();";
+ }
+
+ os << "}";
+ }
+
+ // Member callbacks.
+ //
+ if (!restriction_p (c))
+ {
+ if (ha || haa)
+ names (c, names_attribute_callback_);
+ }
+
+ if (he || hae)
+ contains_compositor (c, contains_compositor_callback_);
+
+ // reset
+ //
+ if (!restriction_p (c) && (he || ha) && reset)
+ {
+ os << "void " << name << "::" << endl
+ << "_reset ()"
+ << "{";
+
+ // Avoid recursion in case of recursive parsing.
+ //
+ if (he)
+ os << "if (this->resetting_)" << endl
+ << "return;"
+ << endl;
+
+ // Reset the base. We cannot use the fully-qualified base name
+ // directly because of some broken compilers (EVC 4.0).
+ //
+ String base (unclash (name, "base"));
+
+ os << "typedef ";
+
+ if (hb)
+ os << fq_name (c.inherits ().base ());
+ else
+ os << complex_base;
+
+ os << " " << base << ";"
+ << base << "::_reset ();"
+ << endl;
+
+ // Reset member serializer.
+ //
+
+ if (ha)
+ names (c, names_attribute_reset_);
+
+ if (he)
+ {
+ os << "this->resetting_ = true;"
+ << endl;
+
+ contains_compositor (c, contains_compositor_reset_);
+
+ os << "this->resetting_ = false;"
+ << endl;
+ }
+
+ os << "}";
+ }
+
+ //
+ //
+ if (poly_code)
+ {
+ String id (c.name ());
+
+ if (String ns = xml_ns_name (c))
+ {
+ id += L' ';
+ id += ns;
+ }
+
+ os << "const char* " << name << "::" << endl
+ << "_static_type ()"
+ << "{"
+ << "return " << strlit (id) << ";"
+ << "}";
+
+ os << "const char* " << name << "::" << endl
+ << "_dynamic_type () const"
+ << "{"
+ << "return _static_type ();"
+ << "}";
+
+ if (hb && validation)
+ {
+ Boolean gen (!anonymous (c));
+
+ // We normally don't need to enter anonymous types into
+ // the inheritance map. The only exception is when an
+ // anonymous types is defined inside an element that
+ // is a member of a substitution group.
+ //
+ if (!gen)
+ {
+ // The first instance that this anonymous type classifies
+ // is the prototype for others if any.
+ //
+ SemanticGraph::Instance& i (
+ c.classifies_begin ()->instance ());
+
+ if (SemanticGraph::Element* e =
+ dynamic_cast<SemanticGraph::Element*> (&i))
+ {
+ if (e->substitutes_p ())
+ gen = true;
+ }
+ }
+
+ if (gen)
+ {
+ SemanticGraph::Type& base (c.inherits ().base ());
+
+ os << "static" << endl
+ << "const ::xsde::cxx::serializer::validating::" <<
+ "inheritance_map_entry" << endl
+ << "_xsde_" << name << "_inheritance_map_entry_ (" << endl
+ << name << "::_static_type ()," << endl
+ << fq_name (base) << "::_static_type ());"
+ << endl;
+ }
+ }
+ }
+
+ if (tiein && hb)
+ {
+ // If our base has pure virtual functions, override them here.
+ //
+ BaseOverride t (*this, name);
+ t.dispatch (c.inherits ().base ());
+ }
+
+ // If we are validating, the rest is generated elsewere.
+ //
+ if (validation)
+ return;
+
+ // Don't use restriction_p here since we don't want special
+ // treatment of anyType.
+ //
+ Boolean restriction (
+ hb && c.inherits ().is_a<SemanticGraph::Restricts> ());
+
+ // _serialize_attributes
+ //
+ if (ha || haa)
+ {
+ os << "void " << name << "::" << endl
+ << "_serialize_attributes ()"
+ << "{";
+
+ // We need context for wildcards only if we are using error
+ // codes.
+ //
+ if (ha || !exceptions)
+ os << "::xsde::cxx::serializer::context& ctx = this->_context ();"
+ << endl;
+
+ if (hb && !restriction)
+ {
+ // We cannot use the fully-qualified base name directly
+ // because of some broken compilers (EVC 4.0).
+ //
+ String base (unclash (name, "base"));
+
+ os << "typedef " << fq_name (c.inherits ().base ()) << " " <<
+ base << ";"
+ << base << "::_serialize_attributes ();"
+ << endl;
+
+ if (!exceptions)
+ {
+ os << "if (ctx.error_type ())" << endl
+ << "return;"
+ << endl;
+ }
+ }
+
+ names (c, names_attribute_);
+
+ os << "}";
+ }
+
+ // _serialize_content
+ //
+ if (he || hae)
+ {
+ os << "void " << name << "::" << endl
+ << "_serialize_content ()"
+ << "{";
+
+ // We need context for wildcards only if we are using error
+ // codes.
+ //
+ if (he || !exceptions)
+ os << "::xsde::cxx::serializer::context& ctx = this->_context ();"
+ << endl;
+
+ if (hb && !restriction)
+ {
+ // We cannot use the fully-qualified base name directly
+ // because of some broken compilers (EVC 4.0).
+ //
+ String base (unclash (name, "base"));
+
+ os << "typedef " << fq_name (c.inherits ().base ()) << " " <<
+ base << ";"
+ << base << "::_serialize_content ();"
+ << endl;
+
+ if (!exceptions)
+ {
+ os << "if (ctx.error_type ())" << endl
+ << "return;"
+ << endl;
+ }
+ }
+
+ contains_compositor (c, contains_compositor_);
+
+ os << "}";
+ }
+ }
+
+ private:
+ //
+ //
+ CompositorCallback compositor_callback_;
+ ParticleCallback particle_callback_;
+ Traversal::ContainsCompositor contains_compositor_callback_;
+ Traversal::ContainsParticle contains_particle_callback_;
+
+ AttributeCallback attribute_callback_;
+ Traversal::Names names_attribute_callback_;
+
+ //
+ //
+ Traversal::Compositor compositor_reset_;
+ ParticleReset particle_reset_;
+ Traversal::ContainsCompositor contains_compositor_reset_;
+ Traversal::ContainsParticle contains_particle_reset_;
+
+ AttributeReset attribute_reset_;
+ Traversal::Names names_attribute_reset_;
+
+ //
+ //
+ Compositor compositor_;
+ Particle particle_;
+ Traversal::ContainsCompositor contains_compositor_;
+ Traversal::ContainsParticle contains_particle_;
+
+ Attribute attribute_;
+ Traversal::Names names_attribute_;
+ };
+
+
+ // Generate substitution group map entries.
+ //
+ struct GlobalElement: Traversal::Element, Context
+ {
+ GlobalElement (Context& c)
+ : Context (c)
+ {
+ }
+
+ virtual Void
+ traverse (Type& e)
+ {
+ if (e.substitutes_p ())
+ {
+ String name (escape (e.name ()));
+ Type& r (e.substitutes ().root ());
+
+ SemanticGraph::Type& type (e.type ());
+
+ String r_id (r.name ());
+
+ if (String const& ns = r.namespace_ ().name ())
+ {
+ r_id += L' ';
+ r_id += ns;
+ }
+
+ os << "// Substitution map entry for " << comment (e.name ()) <<
+ "." << endl
+ << "//" << endl
+ << "static" << endl
+ << "const ::xsde::cxx::serializer::substitution_map_entry" << endl
+ << "_xsde_" << name << "_substitution_map_entry_ (" << endl
+ << strlit (r_id) << "," << endl;
+
+ if (String const& ns = e.namespace_ ().name ())
+ os << strlit (ns) << "," << endl;
+ else
+ os << "0," << endl;
+
+ os << strlit (e.name ()) << "," << endl
+ << fq_name (type) << "::_static_type ());"
+ << endl;
+ }
+ }
+ };
+ }
+
+ Void
+ generate_serializer_source (Context& ctx)
+ {
+ if (ctx.tiein)
+ ctx.os << "#include <assert.h>" << endl
+ << endl;
+
+ if (ctx.poly_code)
+ {
+ ctx.os << "#include <string.h>" << endl
+ << "#include <xsde/cxx/serializer/substitution-map.hxx>" << endl;
+
+ if (ctx.validation)
+ ctx.os << "#include <xsde/cxx/serializer/validating/inheritance-map.hxx>" << endl
+ << endl;
+ else
+ ctx.os << endl;
+
+ ctx.os << "static" << endl
+ << "const ::xsde::cxx::serializer::substitution_map_init" << endl
+ << "_xsde_substitution_map_init_;"
+ << endl;
+
+ if (ctx.validation)
+ {
+ ctx.os << "static" << endl
+ << "const ::xsde::cxx::serializer::validating::" <<
+ "inheritance_map_init" << endl
+ << "_xsde_inheritance_map_init_;"
+ << endl;
+ }
+ }
+
+ // Emit "weak" header includes that are used in the file-per-type
+ // compilation model.
+ //
+ if (ctx.options.value<CLI::generate_inline> ())
+ {
+ Traversal::Schema schema;
+ Includes includes (ctx, Includes::source);
+
+ schema >> includes;
+ schema.dispatch (ctx.schema_root);
+ }
+
+ Traversal::Schema schema;
+
+ Traversal::Sources sources;
+ Traversal::Names schema_names;
+
+ Namespace ns (ctx);
+ Traversal::Names names;
+
+ schema >> sources >> schema;
+ schema >> schema_names >> ns >> names;
+
+ List list (ctx);
+ Union union_ (ctx);
+ Complex complex (ctx);
+ Enumeration enumeration (ctx);
+ GlobalElement global_element (ctx);
+
+ names >> list;
+ names >> union_;
+ names >> complex;
+ names >> enumeration;
+
+ if (ctx.poly_code)
+ names >> global_element;
+
+ schema.dispatch (ctx.schema_root);
+ }
+ }
+}
diff --git a/xsde/cxx/serializer/serializer-source.hxx b/xsde/cxx/serializer/serializer-source.hxx
new file mode 100644
index 0000000..6b1353e
--- /dev/null
+++ b/xsde/cxx/serializer/serializer-source.hxx
@@ -0,0 +1,22 @@
+// file : xsde/cxx/serializer/serializer-source.hxx
+// author : Boris Kolpackov <boris@codesynthesis.com>
+// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC
+// license : GNU GPL v2 + exceptions; see accompanying LICENSE file
+
+#ifndef CXX_SERIALIZER_SERIALIZER_SOURCE_HXX
+#define CXX_SERIALIZER_SERIALIZER_SOURCE_HXX
+
+#include <xsd-frontend/semantic-graph/schema.hxx>
+
+#include <cxx/serializer/elements.hxx>
+
+namespace CXX
+{
+ namespace Serializer
+ {
+ Void
+ generate_serializer_source (Context&);
+ }
+}
+
+#endif // CXX_SERIALIZER_SERIALIZER_SOURCE_HXX
diff --git a/xsde/cxx/serializer/type-processor.cxx b/xsde/cxx/serializer/type-processor.cxx
new file mode 100644
index 0000000..6854e2c
--- /dev/null
+++ b/xsde/cxx/serializer/type-processor.cxx
@@ -0,0 +1,356 @@
+// file : xsde/cxx/serializer/type-processor.cxx
+// author : Boris Kolpackov <boris@codesynthesis.com>
+// copyright : Copyright (c) 2006-2009 Code Synthesis Tools CC
+// license : GNU GPL v2 + exceptions; see accompanying LICENSE file
+
+#include <cult/containers/set.hxx>
+
+#include <cxx/serializer/elements.hxx>
+#include <cxx/serializer/type-processor.hxx>
+
+#include <xsd-frontend/semantic-graph.hxx>
+#include <xsd-frontend/traversal.hxx>
+
+namespace CXX
+{
+ namespace Serializer
+ {
+ namespace
+ {
+ //
+ //
+ struct Type: Traversal::Type
+ {
+ Type (SemanticGraph::Schema& schema,
+ TypeMap::Namespaces& type_map,
+ Boolean add_includes)
+ : schema_ (schema),
+ type_map_ (type_map),
+ add_includes_ (add_includes)
+ {
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Type& type)
+ {
+ using TypeMap::Namespace;
+ using TypeMap::Namespaces;
+
+ SemanticGraph::Context& tc (type.context ());
+
+ // There are two situations where we may try to process the
+ // same type more than once. The first is when the type is
+ // used in several element declarations in the same schema.
+ // The second situation only occurs when we are in the file-
+ // per-type mode. In this case the type was processed as part
+ // of another root schema. In the second case, while the ret
+ // and arg types are assumed to be the same, we need to re-
+ // match the type in order to add include directives to the
+ // new root schema.
+ //
+ Boolean set (true);
+
+ if (tc.count ("s:ret-type"))
+ {
+ SemanticGraph::Schema* s (
+ tc.get<SemanticGraph::Schema*> ("s:root-schema"));
+
+ if (&schema_ == s)
+ return;
+
+ set = false;
+ }
+
+ SemanticGraph::Namespace& ns (
+ dynamic_cast<SemanticGraph::Namespace&> (type.scope ()));
+
+ String ns_name (ns.name ());
+ String t_name (type.name ());
+
+ // std::wcerr << "traversing: " << ns_name << "#" << t_name << endl;
+
+ for (Namespaces::ConstIterator n (type_map_.begin ());
+ n != type_map_.end (); ++n)
+ {
+ // Check if the namespace matches.
+ //
+ //@@ Should probably store precompiled regex somewhere
+ // instead of doing it every time.
+ //
+ boost::basic_regex<WideChar> ns_expr;
+
+ Boolean ns_match;
+
+ if (!n->xsd_name ().empty ())
+ {
+ ns_match = n->xsd_name ().match (ns_name);
+ }
+ else
+ ns_match = ns_name.empty ();
+
+ // std::wcerr << "considering ns expr: " << n->xsd_name () << endl;
+
+ if (ns_match)
+ {
+ // Namespace matched. See if there is a type that matches.
+ //
+ for (Namespace::TypesIterator t (n->types_begin ());
+ t != n->types_end (); ++t)
+ {
+ if (t->xsd_name ().match (t_name))
+ {
+ if (set)
+ {
+ // Got a match. See if the namespace has the C++
+ // namespace mapping.
+ //
+ String cxx_ns;
+
+ if (n->has_cxx_name ())
+ {
+ if (!n->xsd_name ().empty ())
+ {
+ cxx_ns = n->xsd_name ().merge (
+ n->cxx_name (), ns_name, true);
+ }
+ else
+ cxx_ns = n->cxx_name ();
+
+ cxx_ns += L"::";
+ }
+
+ // Figure out ret and arg type names.
+ //
+ String ret_type (cxx_ns);
+
+ ret_type += t->xsd_name ().merge (
+ t->cxx_ret_name (), t_name, true);
+
+ String arg_type;
+
+ if (t->cxx_arg_name ())
+ {
+ arg_type = cxx_ns;
+ arg_type += t->xsd_name ().merge (
+ t->cxx_arg_name (), t_name, true);
+ }
+ else
+ {
+ if (ret_type == L"void")
+ arg_type = ret_type;
+ else
+ {
+ WideChar last (ret_type[ret_type.size () - 1]);
+
+ // If it is already a pointer or reference then use
+ // it as is.
+ //
+ if (last == L'*' || last == L'&')
+ arg_type = ret_type;
+ else
+ arg_type = L"const " + ret_type + L"&";
+ }
+ }
+
+ tc.set ("s:ret-type", ret_type);
+ tc.set ("s:arg-type", arg_type);
+ }
+
+ tc.set ("s:root-schema", &schema_);
+
+ //std::wcerr << t_name << " -> " << ret_type << endl;
+
+ // See of we need to add any includes to the translations
+ // unit.
+ //
+ if (add_includes_)
+ {
+ if (n->includes_begin () != n->includes_end ())
+ {
+ typedef Cult::Containers::Set<String> Includes;
+
+ SemanticGraph::Context& sc (schema_.context ());
+
+ if (!sc.count ("s:includes"))
+ sc.set ("s:includes", Includes ());
+
+ Includes& is (sc.get<Includes> ("s:includes"));
+
+ for (Namespace::IncludesIterator i (n->includes_begin ());
+ i != n->includes_end (); ++i)
+ {
+ is.insert (*i);
+ }
+ }
+ }
+
+ return;
+ }
+ }
+ }
+ }
+ }
+
+ private:
+ SemanticGraph::Schema& schema_;
+ TypeMap::Namespaces& type_map_;
+ Boolean add_includes_;
+ };
+
+ //
+ //
+ struct BaseType: Traversal::Complex
+ {
+ virtual Void
+ traverse (SemanticGraph::Complex& c)
+ {
+ Complex::names (c);
+ }
+ };
+
+ //
+ //
+ struct GlobalType: Traversal::Type,
+ Traversal::List,
+ Traversal::Complex,
+ Traversal::Enumeration
+ {
+ GlobalType (SemanticGraph::Schema& schema,
+ TypeMap::Namespaces& type_map,
+ Boolean add_includes,
+ Boolean tiein)
+ : type_ (schema, type_map, add_includes)
+ {
+ inherits_ >> type_;
+ names_ >> instance_ >> belongs_ >> type_;
+ argumented_ >> type_;
+
+ if (tiein)
+ {
+ // In case of a tiein support, we also need to process base's
+ // members to assign ret/arg types.
+ //
+ inherits_base_ >> base_type_ >> names_;
+ }
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Type& t)
+ {
+ type_.traverse (t);
+ }
+
+ virtual Void
+ traverse (SemanticGraph::List& l)
+ {
+ type_.traverse (l);
+ Traversal::List::argumented (l, argumented_);
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Complex& c)
+ {
+ type_.traverse (c);
+ Complex::inherits (c, inherits_);
+ Complex::inherits (c, inherits_base_);
+ Complex::names (c, names_);
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Enumeration& e)
+ {
+ type_.traverse (e);
+ Complex::inherits (e, inherits_);
+ }
+
+ private:
+ Serializer::Type type_;
+ BaseType base_type_;
+ Traversal::Names names_;
+ Traversal::Instance instance_;
+ Traversal::Inherits inherits_;
+ Traversal::Inherits inherits_base_;
+ Traversal::Belongs belongs_;
+ Traversal::Argumented argumented_;
+ };
+
+ Void
+ process_impl (CLI::Options const& options,
+ XSDFrontend::SemanticGraph::Schema& tu,
+ TypeMap::Namespaces& type_map)
+ {
+ Boolean tiein (!options.value<CLI::reuse_style_mixin> () &&
+ !options.value<CLI::reuse_style_none> ());
+
+ if (tu.names_begin ()->named ().name () ==
+ L"http://www.w3.org/2001/XMLSchema")
+ {
+ // XML Schema namespace.
+ //
+ Traversal::Schema schema;
+
+ Traversal::Names schema_names;
+ Traversal::Namespace ns;
+ Traversal::Names ns_names;
+ GlobalType global_type (tu, type_map, true, tiein);
+
+ schema >> schema_names >> ns >> ns_names >> global_type;
+
+ schema.dispatch (tu);
+ }
+ else
+ {
+ // If --extern-xml-schema is specified, then we don't want
+ // includes from the XML Schema type map.
+ //
+ Boolean extern_xml_schema (
+ options.value<CLI::extern_xml_schema> ());
+
+ // Besides types defined in this schema, also process those
+ // referenced by global elements in case we are generating
+ // something for them.
+ //
+ Traversal::Schema schema;
+ Traversal::Schema xs_schema;
+ Traversal::Sources sources;
+ Traversal::Implies implies;
+
+ schema >> sources >> schema;
+ schema >> implies >> xs_schema;
+
+ Traversal::Names schema_names;
+ Traversal::Namespace ns;
+ Traversal::Names ns_names;
+ Traversal::Element global_element;
+ GlobalType global_type (tu, type_map, true, tiein);
+
+ schema >> schema_names >> ns >> ns_names;
+
+ ns_names >> global_element;
+ ns_names >> global_type;
+
+ Traversal::Belongs element_belongs;
+ global_element >> element_belongs >> global_type;
+
+ Traversal::Names xs_schema_names;
+ Traversal::Namespace xs_ns;
+ Traversal::Names xs_ns_names;
+ GlobalType xs_global_type (tu, type_map, !extern_xml_schema, tiein);
+
+ xs_schema >> xs_schema_names >> xs_ns >> xs_ns_names >>
+ xs_global_type;
+
+ schema.dispatch (tu);
+ }
+ }
+ }
+
+ Void TypeProcessor::
+ process (CLI::Options const& options,
+ XSDFrontend::SemanticGraph::Schema& s,
+ TypeMap::Namespaces& tm)
+ {
+ process_impl (options, s, tm);
+ }
+ }
+}
diff --git a/xsde/cxx/serializer/type-processor.hxx b/xsde/cxx/serializer/type-processor.hxx
new file mode 100644
index 0000000..8408a4e
--- /dev/null
+++ b/xsde/cxx/serializer/type-processor.hxx
@@ -0,0 +1,34 @@
+// file : xsde/cxx/serializer/type-processor.hxx
+// author : Boris Kolpackov <boris@codesynthesis.com>
+// copyright : Copyright (c) 2006-2009 Code Synthesis Tools CC
+// license : GNU GPL v2 + exceptions; see accompanying LICENSE file
+
+#ifndef CXX_SERIALIZER_TYPE_PROCESSOR_HXX
+#define CXX_SERIALIZER_TYPE_PROCESSOR_HXX
+
+#include <cult/types.hxx>
+
+#include <xsd-frontend/semantic-graph.hxx>
+
+#include <type-map/type-map.hxx>
+
+#include <cxx/serializer/cli.hxx>
+
+namespace CXX
+{
+ namespace Serializer
+ {
+ using namespace Cult::Types;
+
+ class TypeProcessor
+ {
+ public:
+ Void
+ process (CLI::Options const& options,
+ XSDFrontend::SemanticGraph::Schema&,
+ TypeMap::Namespaces&);
+ };
+ }
+}
+
+#endif // CXX_SERIALIZER_TYPE_PROCESSOR_HXX
diff --git a/xsde/cxx/serializer/validator.cxx b/xsde/cxx/serializer/validator.cxx
new file mode 100644
index 0000000..d9cc724
--- /dev/null
+++ b/xsde/cxx/serializer/validator.cxx
@@ -0,0 +1,501 @@
+// file : xsde/cxx/serializer/validator.cxx
+// author : Boris Kolpackov <boris@codesynthesis.com>
+// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC
+// license : GNU GPL v2 + exceptions; see accompanying LICENSE file
+
+#include <cxx/serializer/validator.hxx>
+
+#include <xsd-frontend/semantic-graph.hxx>
+#include <xsd-frontend/traversal.hxx>
+
+#include <cxx/serializer/elements.hxx>
+
+#include <iostream>
+
+using std::wcerr;
+
+namespace CXX
+{
+ namespace Serializer
+ {
+ namespace
+ {
+ class ValidationContext: public Context
+ {
+ public:
+ ValidationContext (SemanticGraph::Schema& root,
+ CLI::Options const& options,
+ const WarningSet& disabled_warnings,
+ Boolean& valid_)
+ : Context (std::wcerr, root, options, 0, 0, 0),
+ disabled_warnings_ (disabled_warnings),
+ disabled_warnings_all_ (false),
+ valid (valid_),
+ subst_group_warning_issued (subst_group_warning_issued_),
+ subst_group_warning_issued_ (false)
+ {
+ }
+
+ public:
+ Boolean
+ is_disabled (Char const* w)
+ {
+ return disabled_warnings_all_ ||
+ disabled_warnings_.find (w) != disabled_warnings_.end ();
+ }
+
+ public:
+ String
+ xpath (SemanticGraph::Nameable& n)
+ {
+ if (n.is_a<SemanticGraph::Namespace> ())
+ return L"<namespace-level>"; // There is a bug if you see this.
+
+ assert (n.named ());
+
+ SemanticGraph::Scope& scope (n.scope ());
+
+ if (scope.is_a<SemanticGraph::Namespace> ())
+ return n.name ();
+
+ return xpath (scope) + L"/" + n.name ();
+ }
+
+ protected:
+ ValidationContext (ValidationContext& c)
+ : Context (c),
+ disabled_warnings_ (c.disabled_warnings_),
+ disabled_warnings_all_ (c.disabled_warnings_all_),
+ valid (c.valid),
+ subst_group_warning_issued (c.subst_group_warning_issued)
+ {
+ }
+
+ protected:
+ const WarningSet& disabled_warnings_;
+ Boolean disabled_warnings_all_;
+ Boolean& valid;
+ Boolean& subst_group_warning_issued;
+ Boolean subst_group_warning_issued_;
+ };
+
+ //
+ //
+ struct Traverser : Traversal::Schema,
+ Traversal::Complex,
+ Traversal::Type,
+ Traversal::Element,
+ ValidationContext
+ {
+ Traverser (ValidationContext& c)
+ : ValidationContext (c)
+ {
+ *this >> sources_ >> *this;
+ *this >> schema_names_ >> ns_ >> names_ >> *this;
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Complex& c)
+ {
+ using SemanticGraph::Schema;
+
+ traverse (static_cast<SemanticGraph::Type&> (c));
+
+ if (c.inherits_p ())
+ {
+ SemanticGraph::Type& t (c.inherits ().base ());
+
+ if (t.named () &&
+ types_.find (
+ t.scope ().name () + L"#" + t.name ()) == types_.end ())
+ {
+ // Don't worry about types that are in included/imported
+ // schemas.
+ //
+ Schema& s (dynamic_cast<Schema&> (t.scope ().scope ()));
+
+ if (&s == &schema_root || sources_p (schema_root, s))
+ {
+ valid = false;
+
+ wcerr << c.file () << ":" << c.line () << ":" << c.column ()
+ << ": error: type '" << xpath (c) << "' inherits from "
+ << "yet undefined type '" << xpath (t) << "'" << endl;
+
+ wcerr << t.file () << ":" << t.line () << ":" << t.column ()
+ << ": info: '" << xpath (t) << "' is defined here"
+ << endl;
+
+ wcerr << c.file () << ":" << c.line () << ":" << c.column ()
+ << ": info: inheritance from a yet-undefined type is "
+ << "not supported" << endl;
+
+ wcerr << c.file () << ":" << c.line () << ":" << c.column ()
+ << ": info: re-arrange your schema and try again"
+ << endl;
+ }
+ }
+ }
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Type& t)
+ {
+ if (t.named ())
+ {
+ types_.insert (t.scope ().name () + L"#" + t.name ());
+ }
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Element& e)
+ {
+ if (is_disabled ("S001"))
+ return;
+
+ if (e.substitutes_p () &&
+ !options.value<CLI::generate_polymorphic> () &&
+ !subst_group_warning_issued)
+ {
+ subst_group_warning_issued = true;
+
+ os << e.file () << ":" << e.line () << ":" << e.column ()
+ << ": warning S001: substitution groups are used but "
+ << "--generate-polymorphic was not specified" << endl;
+
+ os << e.file () << ":" << e.line () << ":" << e.column ()
+ << ": info: generated code may not be able to serialize "
+ << "some conforming instances" << endl;
+ }
+ }
+
+ // Return true if root sources s.
+ //
+ Boolean
+ sources_p (SemanticGraph::Schema& root, SemanticGraph::Schema& s)
+ {
+ using SemanticGraph::Schema;
+ using SemanticGraph::Sources;
+
+ for (Schema::UsesIterator i (root.uses_begin ());
+ i != root.uses_end (); ++i)
+ {
+ if (i->is_a<Sources> ())
+ {
+ if (&i->schema () == &s || sources_p (i->schema (), s))
+ return true;
+ }
+ }
+
+ return false;
+ }
+
+ private:
+ Containers::Set<String> types_;
+
+ Traversal::Sources sources_;
+
+ Traversal::Names schema_names_;
+ Traversal::Namespace ns_;
+
+ Traversal::Names names_;
+ };
+
+ //
+ //
+ struct AnonymousMember: protected ValidationContext
+ {
+ AnonymousMember (ValidationContext& c, Boolean& error_issued)
+ : ValidationContext (c), error_issued_ (error_issued)
+ {
+ }
+
+ Boolean
+ traverse_common (SemanticGraph::Member& m)
+ {
+ SemanticGraph::Type& t (m.type ());
+
+ if (!t.named ()
+ && !t.is_a<SemanticGraph::Fundamental::IdRef> ()
+ && !t.is_a<SemanticGraph::Fundamental::IdRefs> ())
+ {
+ if (!error_issued_)
+ {
+ valid = false;
+ error_issued_ = true;
+
+ wcerr << t.file ()
+ << ": error: anonymous types detected"
+ << endl;
+
+ wcerr << t.file ()
+ << ": info: "
+ << "anonymous types are not supported in this mapping"
+ << endl;
+
+ wcerr << t.file ()
+ << ": info: consider explicitly naming these types or "
+ << "remove the --preserve-anonymous option to "
+ << "automatically name them"
+ << endl;
+
+ if (!options.value<CLI::show_anonymous> ())
+ wcerr << t.file ()
+ << ": info: use --show-anonymous option to see these "
+ << "types" << endl;
+ }
+
+ return true;
+ }
+
+ return false;
+ }
+
+ private:
+ Boolean& error_issued_;
+ };
+
+ struct AnonymousElement: Traversal::Element,
+ AnonymousMember
+ {
+ AnonymousElement (ValidationContext& c, Boolean& error_issued)
+ : AnonymousMember (c, error_issued)
+ {
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Element& e)
+ {
+ if (traverse_common (e))
+ {
+ if (options.value<CLI::show_anonymous> ())
+ {
+ wcerr << e.file () << ":" << e.line () << ":" << e.column ()
+ << ": error: element '" << xpath (e) << "' "
+ << "is of anonymous type" << endl;
+ }
+ }
+ else
+ Traversal::Element::traverse (e);
+ }
+ };
+
+ struct AnonymousAttribute: Traversal::Attribute,
+ AnonymousMember
+ {
+ AnonymousAttribute (ValidationContext& c, Boolean& error_issued)
+ : AnonymousMember (c, error_issued)
+ {
+ }
+
+ virtual Void
+ traverse (Type& a)
+ {
+ if (traverse_common (a))
+ {
+ if (options.value<CLI::show_anonymous> ())
+ {
+ wcerr << a.file () << ":" << a.line () << ":" << a.column ()
+ << ": error: attribute '" << xpath (a) << "' "
+ << "is of anonymous type" << endl;
+ }
+ }
+ else
+ Traversal::Attribute::traverse (a);
+ }
+ };
+
+ struct AnonymousType : Traversal::Schema,
+ Traversal::Complex,
+ ValidationContext
+ {
+ AnonymousType (ValidationContext& c)
+ : ValidationContext (c),
+ error_issued_ (false),
+ element_ (c, error_issued_),
+ attribute_ (c, error_issued_)
+ {
+ *this >> sources_ >> *this;
+ *this >> schema_names_ >> ns_ >> names_ >> *this;
+
+ *this >> contains_compositor_ >> compositor_;
+ compositor_ >> contains_particle_;
+ contains_particle_ >> compositor_;
+ contains_particle_ >> element_;
+
+ *this >> names_attribute_ >> attribute_;
+ }
+
+ private:
+ Boolean error_issued_;
+
+ Containers::Set<String> types_;
+
+ Traversal::Sources sources_;
+
+ Traversal::Names schema_names_;
+ Traversal::Namespace ns_;
+ Traversal::Names names_;
+
+ Traversal::Compositor compositor_;
+ AnonymousElement element_;
+ Traversal::ContainsCompositor contains_compositor_;
+ Traversal::ContainsParticle contains_particle_;
+
+ AnonymousAttribute attribute_;
+ Traversal::Names names_attribute_;
+ };
+
+ struct GlobalElement: Traversal::Element, ValidationContext
+ {
+ GlobalElement (ValidationContext& c, SemanticGraph::Element*& element)
+ : ValidationContext (c), element_ (element)
+ {
+ }
+
+ virtual Void
+ traverse (Type& e)
+ {
+ if (!valid)
+ return;
+
+ if (options.value<CLI::root_element_first> ())
+ {
+ if (element_ == 0)
+ element_ = &e;
+ }
+ else if (options.value<CLI::root_element_last> ())
+ {
+ element_ = &e;
+ }
+ else if (String name = options.value<CLI::root_element> ())
+ {
+ if (e.name () == name)
+ element_ = &e;
+ }
+ else
+ {
+ if (element_ == 0)
+ element_ = &e;
+ else
+ {
+ wcerr << schema_root.file () << ": error: unable to generate "
+ << "the test driver without a unique document root"
+ << endl;
+
+ wcerr << schema_root.file () << ": info: use --root-element-* "
+ << "options to specify the document root" << endl;
+
+ valid = false;
+ }
+ }
+ }
+
+ private:
+ SemanticGraph::Element*& element_;
+ };
+ }
+
+ Boolean Validator::
+ validate (CLI::Options const& options,
+ SemanticGraph::Schema& root,
+ SemanticGraph::Path const&,
+ Boolean gen_driver,
+ const WarningSet& disabled_warnings)
+ {
+ Boolean valid (true);
+ ValidationContext ctx (root, options, disabled_warnings, valid);
+
+ //
+ //
+ {
+ Boolean ref (options.value<CLI::root_element_first> ());
+ Boolean rel (options.value<CLI::root_element_last> ());
+ Boolean re (options.value<CLI::root_element> ());
+
+ if ((ref && rel) || (ref && re) || (rel && re))
+ {
+ wcerr << "error: mutually exclusive options specified: "
+ << "--root-element-last, --root-element-first, and "
+ << "--root-element"
+ << endl;
+
+ return false;
+ }
+ }
+
+ //
+ //
+ if (options.value<CLI::reuse_style_mixin> () &&
+ options.value<CLI::reuse_style_none> ())
+ {
+ wcerr << "error: mutually exclusive options specified: "
+ << "--reuse-style-mixin and --reuse-style-none"
+ << endl;
+
+ return false;
+ }
+
+ //
+ //
+ if (options.value<CLI::reuse_style_none> () &&
+ options.value<CLI::generate_empty_impl> () &&
+ !ctx.is_disabled ("S002"))
+ {
+ wcerr << "warning S002: generating sample implementation without "
+ << "serializer reuse support: the resulting code may not "
+ << "compile"
+ << endl;
+
+ return false;
+ }
+
+ // Test for anonymout types.
+ //
+ {
+ AnonymousType traverser (ctx);
+ traverser.dispatch (root);
+ }
+
+ // Test the rest.
+ //
+ if (valid)
+ {
+ Traverser traverser (ctx);
+ traverser.dispatch (root);
+ }
+
+ // Test that the document root is unique.
+ //
+ if (valid && gen_driver)
+ {
+ SemanticGraph::Element* element (0);
+
+ Traversal::Schema schema;
+ Traversal::Sources sources;
+
+ schema >> sources >> schema;
+
+ Traversal::Names schema_names;
+ Traversal::Namespace ns;
+ Traversal::Names ns_names;
+ GlobalElement global_element (ctx, element);
+
+ schema >> schema_names >> ns >> ns_names >> global_element;
+
+ schema.dispatch (root);
+
+ if (valid && element == 0)
+ {
+ wcerr << root.file () << ": error: unable to generate the "
+ << "test driver without a global element (document root)"
+ << endl;
+
+ valid = false;
+ }
+ }
+
+ return valid;
+ }
+ }
+}
diff --git a/xsde/cxx/serializer/validator.hxx b/xsde/cxx/serializer/validator.hxx
new file mode 100644
index 0000000..03d1349
--- /dev/null
+++ b/xsde/cxx/serializer/validator.hxx
@@ -0,0 +1,36 @@
+// file : xsde/cxx/serializer/validator.hxx
+// author : Boris Kolpackov <boris@codesynthesis.com>
+// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC
+// license : GNU GPL v2 + exceptions; see accompanying LICENSE file
+
+#ifndef CXX_SERIALIZER_VALIDATOR_HXX
+#define CXX_SERIALIZER_VALIDATOR_HXX
+
+#include <cult/types.hxx>
+
+#include <xsd-frontend/semantic-graph/schema.hxx>
+
+#include <cxx/serializer/cli.hxx>
+
+#include <xsde.hxx>
+
+namespace CXX
+{
+ namespace Serializer
+ {
+ using namespace Cult::Types;
+
+ class Validator
+ {
+ public:
+ Boolean
+ validate (CLI::Options const& options,
+ XSDFrontend::SemanticGraph::Schema&,
+ XSDFrontend::SemanticGraph::Path const& tu,
+ Boolean gen_driver,
+ const WarningSet& disabled_warnings);
+ };
+ }
+}
+
+#endif // CXX_SERIALIZER_VALIDATOR_HXX