From 0bce70a0e483294b83b8bf9d5468838a63405612 Mon Sep 17 00:00:00 2001 From: Boris Kolpackov Date: Sun, 8 Mar 2009 17:23:30 +0200 Subject: Add support for binary representations xsde/cxx/hybrid/insertion-*: insertion operators generator xsde/cxx/hybrid/extraction-*: extraction operators generator libxsde/xsde/cxx/hybrid/cdr/: CDR support code libxsde/xsde/cxx/hybrid/xdr/: XDR support code tests/cxx/hybrid/binary/: new tests examples/cxx/hybrid/binary/: new examples documentation/cxx/hybrid/guide/: new chapter --- xsde/cxx/hybrid/cli.hxx | 4 + xsde/cxx/hybrid/elements.cxx | 42 +- xsde/cxx/hybrid/elements.hxx | 37 +- xsde/cxx/hybrid/extraction-header.cxx | 255 ++++++++ xsde/cxx/hybrid/extraction-header.hxx | 22 + xsde/cxx/hybrid/extraction-source.cxx | 1063 +++++++++++++++++++++++++++++++++ xsde/cxx/hybrid/extraction-source.hxx | 22 + xsde/cxx/hybrid/generator.cxx | 30 +- xsde/cxx/hybrid/insertion-header.cxx | 255 ++++++++ xsde/cxx/hybrid/insertion-header.hxx | 22 + xsde/cxx/hybrid/insertion-source.cxx | 694 +++++++++++++++++++++ xsde/cxx/hybrid/insertion-source.hxx | 22 + xsde/cxx/hybrid/tree-forward.cxx | 87 +++ xsde/cxx/hybrid/tree-header.cxx | 3 - xsde/makefile | 4 + 15 files changed, 2555 insertions(+), 7 deletions(-) create mode 100644 xsde/cxx/hybrid/extraction-header.cxx create mode 100644 xsde/cxx/hybrid/extraction-header.hxx create mode 100644 xsde/cxx/hybrid/extraction-source.cxx create mode 100644 xsde/cxx/hybrid/extraction-source.hxx create mode 100644 xsde/cxx/hybrid/insertion-header.cxx create mode 100644 xsde/cxx/hybrid/insertion-header.hxx create mode 100644 xsde/cxx/hybrid/insertion-source.cxx create mode 100644 xsde/cxx/hybrid/insertion-source.hxx (limited to 'xsde') diff --git a/xsde/cxx/hybrid/cli.hxx b/xsde/cxx/hybrid/cli.hxx index 57aa3d4..be680ea 100644 --- a/xsde/cxx/hybrid/cli.hxx +++ b/xsde/cxx/hybrid/cli.hxx @@ -33,6 +33,8 @@ namespace CXX extern Key suppress_validation; extern Key suppress_parser_val; extern Key suppress_serializer_val; + extern Key generate_insertion; + extern Key generate_extraction; extern Key generate_inline; extern Key generate_forward; extern Key generate_xml_schema; @@ -111,6 +113,8 @@ namespace CXX suppress_validation, Boolean, suppress_parser_val, Boolean, suppress_serializer_val, Boolean, + generate_insertion, Cult::Containers::Vector, + generate_extraction, Cult::Containers::Vector, generate_inline, Boolean, generate_forward, Boolean, generate_xml_schema, Boolean, diff --git a/xsde/cxx/hybrid/elements.cxx b/xsde/cxx/hybrid/elements.cxx index 454d0c3..c7609ff 100644 --- a/xsde/cxx/hybrid/elements.cxx +++ b/xsde/cxx/hybrid/elements.cxx @@ -41,11 +41,29 @@ namespace CXX fwd_expr (fe), hxx_expr (he), ixx_expr (ie), - ns_stack (ns_stack_) + ns_stack (ns_stack_), + istreams (ops.value ()), + ostreams (ops.value ()), + icdrstream (icdrstream_), + ocdrstream (ocdrstream_), + ixdrstream (ixdrstream_), + oxdrstream (oxdrstream_) { String xs_ns (xs_ns_name ()); string_type = L"::xsde::cxx::ro_string"; + + if (!ostreams.empty ()) + { + ocdrstream = xs_ns + L"::ocdrstream"; + oxdrstream = xs_ns + L"::oxdrstream"; + } + + if (!istreams.empty ()) + { + icdrstream = xs_ns + L"::icdrstream"; + ixdrstream = xs_ns + L"::ixdrstream"; + } } // Parser @@ -384,6 +402,28 @@ namespace CXX } } + String Context:: + istream (NarrowString const& is) const + { + if (is == "CDR") + return icdrstream; + else if (is == "XDR") + return ixdrstream; + else + return is; + } + + String Context:: + ostream (NarrowString const& os) const + { + if (os == "CDR") + return ocdrstream; + else if (os == "XDR") + return oxdrstream; + else + return os; + } + // Namespace // Namespace:: diff --git a/xsde/cxx/hybrid/elements.hxx b/xsde/cxx/hybrid/elements.hxx index 816c80f..73caa35 100644 --- a/xsde/cxx/hybrid/elements.hxx +++ b/xsde/cxx/hybrid/elements.hxx @@ -49,7 +49,13 @@ namespace CXX fwd_expr (c.fwd_expr), hxx_expr (c.hxx_expr), ixx_expr (c.ixx_expr), - ns_stack (c.ns_stack) + ns_stack (c.ns_stack), + istreams (c.istreams), + ostreams (c.ostreams), + icdrstream (c.icdrstream), + ocdrstream (c.ocdrstream), + ixdrstream (c.ixdrstream), + oxdrstream (c.oxdrstream) { } @@ -66,7 +72,13 @@ namespace CXX fwd_expr (c.fwd_expr), hxx_expr (c.hxx_expr), ixx_expr (c.ixx_expr), - ns_stack (c.ns_stack) + ns_stack (c.ns_stack), + istreams (c.istreams), + ostreams (c.ostreams), + icdrstream (c.icdrstream), + ocdrstream (c.ocdrstream), + ixdrstream (c.ixdrstream), + oxdrstream (c.oxdrstream) { } @@ -468,6 +480,13 @@ namespace CXX } public: + String + istream (NarrowString const& is) const; + + String + ostream (NarrowString const& os) const; + + public: Void close_ns (); @@ -496,8 +515,22 @@ namespace CXX NamespaceStack& ns_stack; + typedef Containers::Vector Streams; + Streams const& istreams; + Streams const& ostreams; + + String& icdrstream; + String& ocdrstream; + String& ixdrstream; + String& oxdrstream; + private: NamespaceStack ns_stack_; + + String icdrstream_; + String ocdrstream_; + String ixdrstream_; + String oxdrstream_; }; // diff --git a/xsde/cxx/hybrid/extraction-header.cxx b/xsde/cxx/hybrid/extraction-header.cxx new file mode 100644 index 0000000..8b7490f --- /dev/null +++ b/xsde/cxx/hybrid/extraction-header.cxx @@ -0,0 +1,255 @@ +// file : xsd/cxx/hybrid/extraction-header.cxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#include + +#include +#include + +namespace CXX +{ + namespace Hybrid + { + namespace + { + struct List : Traversal::List, Context + { + List (Context& c) + : Context (c) + { + } + + virtual Void + traverse (Type& l) + { + String name (ename (l)); + + for (Streams::ConstIterator i (istreams.begin ()); + i != istreams.end (); ++i) + { + os << (exceptions ? "void" : "bool") << endl + << "operator>> (" << istream (*i) << "&," << endl + << name << "&);" + << endl; + } + } + }; + + struct Union : Traversal::Union, Context + { + Union (Context& c) + : Context (c) + { + } + + virtual Void + traverse (Type& u) + { + String name (ename (u)); + + for (Streams::ConstIterator i (istreams.begin ()); + i != istreams.end (); ++i) + { + os << (exceptions ? "void" : "bool") << endl + << "operator>> (" << istream (*i) << "&," << endl + << name << "&);" + << endl; + } + } + }; + + // + // Nested classes. + // + + struct All: Traversal::All, Context + { + All (Context& c) + : Context (c) + { + } + + virtual Void + traverse (SemanticGraph::All& a) + { + // For the all compositor, maxOccurs=1 and minOccurs={0,1} + // and it can only contain particles. + // + if (a.min () == 0) + { + String const& type (etype (a)); + String const& scope (Context::scope (a)); + + for (Streams::ConstIterator i (istreams.begin ()); + i != istreams.end (); ++i) + { + os << (exceptions ? "void" : "bool") << endl + << "operator>> (" << istream (*i) << "&," << endl + << scope << "::" << type << "&);" + << endl; + } + } + } + }; + + struct Choice: Traversal::Choice, Context + { + Choice (Context& c, Boolean in_choice) + : Context (c), in_choice_ (in_choice) + { + } + + virtual Void + traverse (SemanticGraph::Choice& c) + { + // When choice is in choice we generate nested class even + // for min == max == 1. + // + if (in_choice_ || c.max () != 1 || c.min () == 0) + { + String const& type (etype (c)); + String const& scope (Context::scope (c)); + + for (Streams::ConstIterator i (istreams.begin ()); + i != istreams.end (); ++i) + { + os << (exceptions ? "void" : "bool") << endl + << "operator>> (" << istream (*i) << "&," << endl + << scope << "::" << type << "&);" + << endl; + } + } + + Choice::contains (c); + } + + private: + Boolean in_choice_; + }; + + + struct Sequence: Traversal::Sequence, Context + { + Sequence (Context& c, Boolean in_choice) + : Context (c), in_choice_ (in_choice) + { + } + + virtual Void + traverse (SemanticGraph::Sequence& s) + { + // When sequence is in choice we generate nested class even + // for min == max == 1. + // + if (in_choice_ || s.max () != 1 || s.min () == 0) + { + String const& type (etype (s)); + String const& scope (Context::scope (s)); + + for (Streams::ConstIterator i (istreams.begin ()); + i != istreams.end (); ++i) + { + os << (exceptions ? "void" : "bool") << endl + << "operator>> (" << istream (*i) << "&," << endl + << scope << "::" << type << "&);" + << endl; + } + } + + Sequence::contains (s); + } + + private: + Boolean in_choice_; + }; + + struct Complex : Traversal::Complex, Context + { + Complex (Context& c) + : Context (c), + all_ (c), + choice_in_choice_ (c, true), + choice_in_sequence_ (c, false), + sequence_in_choice_ (c, true), + sequence_in_sequence_ (c, false) + { + all_ >> all_contains_; + + choice_in_choice_ >> choice_contains_; + choice_in_sequence_ >> choice_contains_; + choice_contains_ >> choice_in_choice_; + choice_contains_ >> sequence_in_choice_; + + sequence_in_choice_ >> sequence_contains_; + sequence_in_sequence_ >> sequence_contains_; + sequence_contains_ >> choice_in_sequence_; + sequence_contains_ >> sequence_in_sequence_; + + contains_compositor_ >> all_; + contains_compositor_ >> choice_in_sequence_; + contains_compositor_ >> sequence_in_sequence_; + } + + virtual Void + traverse (Type& c) + { + if (!restriction_p (c)) + { + String name (ename (c)); + + for (Streams::ConstIterator i (istreams.begin ()); + i != istreams.end (); ++i) + { + os << (exceptions ? "void" : "bool") << endl + << "operator>> (" << istream (*i) << "&," << endl + << name << "&);" + << endl; + } + + // Operators for nested classes. + // + if (c.contains_compositor_p ()) + Complex::contains_compositor (c, contains_compositor_); + } + } + + private: + All all_; + Choice choice_in_choice_; + Choice choice_in_sequence_; + Sequence sequence_in_choice_; + Sequence sequence_in_sequence_; + Traversal::ContainsParticle all_contains_; + Traversal::ContainsParticle choice_contains_; + Traversal::ContainsParticle sequence_contains_; + + Traversal::ContainsCompositor contains_compositor_; + }; + } + + Void + generate_extraction_header (Context& ctx) + { + Traversal::Schema schema; + Traversal::Sources sources; + Traversal::Names names_ns, names; + + Namespace ns (ctx); + + List list (ctx); + Union union_ (ctx); + Complex complex (ctx); + + schema >> sources >> schema; + schema >> names_ns >> ns >> names; + + names >> list; + names >> union_; + names >> complex; + + schema.dispatch (ctx.schema_root); + } + } +} diff --git a/xsde/cxx/hybrid/extraction-header.hxx b/xsde/cxx/hybrid/extraction-header.hxx new file mode 100644 index 0000000..dc5b391 --- /dev/null +++ b/xsde/cxx/hybrid/extraction-header.hxx @@ -0,0 +1,22 @@ +// file : xsde/cxx/hybrid/extraction-header.hxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#ifndef CXX_HYBRID_EXTRACTION_HEADER_HXX +#define CXX_HYBRID_EXTRACTION_HEADER_HXX + +#include + +#include + +namespace CXX +{ + namespace Hybrid + { + Void + generate_extraction_header (Context&); + } +} + +#endif // CXX_HYBRID_EXTRACTION_HEADER_HXX diff --git a/xsde/cxx/hybrid/extraction-source.cxx b/xsde/cxx/hybrid/extraction-source.cxx new file mode 100644 index 0000000..44af7e0 --- /dev/null +++ b/xsde/cxx/hybrid/extraction-source.cxx @@ -0,0 +1,1063 @@ +// file : xsd/cxx/hybrid/extraction-source.cxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#include + +#include +#include + +namespace CXX +{ + namespace Hybrid + { + namespace + { + struct List : Traversal::List, Context + { + List (Context& c) + : Context (c), base_name_ (c, TypeName::seq) + { + } + + virtual Void + traverse (Type& l) + { + String name (ename (l)); + + for (Streams::ConstIterator i (istreams.begin ()); + i != istreams.end (); ++i) + { + os << (exceptions ? "void" : "bool") << endl + << "operator>> (" << istream (*i) << "& s," << endl + << name << "& x)" + << "{"; + + base_name_.dispatch (l.argumented ().type ()); + + os << "& b = x;" + << (exceptions ? "" : "return ") << "s >> b;" + << "}"; + } + } + + private: + TypeName base_name_; + }; + + struct Union : Traversal::Union, Context + { + Union (Context& c) + : Context (c) + { + } + + virtual Void + traverse (Type& u) + { + String name (ename (u)); + String const& value (u.context ().get ("value")); + + for (Streams::ConstIterator i (istreams.begin ()); + i != istreams.end (); ++i) + { + os << (exceptions ? "void" : "bool") << endl + << "operator>> (" << istream (*i) << "& s," << endl + << name << "& x)" + << "{" + << (stl ? "::std::string" : "char*") << " i;"; + + if (exceptions) + os << "s >> i;"; + else + os << "if (!(s >> i))" << endl + << "return false;"; + + os << "x." << value << " (i);" + << (exceptions ? "" : "return true;") + << "}"; + } + } + }; + + // + // Data. + // + + struct AttributeData: Traversal::Attribute, Context + { + AttributeData (Context& c) + : Context (c) + { + } + + virtual Void + traverse (SemanticGraph::Attribute& a) + { + SemanticGraph::Type& t (a.type ()); + + Boolean fl (fixed_length (t)); + Boolean st (false); + + String const& name (ename (a)); + + if (!fl) + { + StringType test (st); + test.dispatch (t); + } + + os << "{"; + + if (a.optional ()) + { + os << "bool p;"; + + if (exceptions) + os << "s >> p;"; + else + os << endl + << "if (!(s >> p))" << endl + << "return false;"; + + os << endl + << "if (p)" + << "{"; + + if (fl) + os << "x." << epresent (a) << " (true);"; + } + + if (st) + { + // C-string requires special handling. + // + os << "char* i;"; + + if (exceptions) + os << "s >> i;"; + else + os << "if (!(s >> i))" << endl + << "return false;"; + + os << "x." << name << " (i);"; + } + else + { + if (!fl) + { + String fq (fq_name (t)); + + if (exceptions) + os << "x." << name << " (new " << fq << ");"; + else + os << fq << "* i = new " << fq << ";" + << endl + << "if (i == 0)" << endl + << "return false;" + << endl + << "x." << name << " (i);"; + } + + if (exceptions) + os << "s >> x." << name << " ();"; + else + os << "if (!(s >> x." << name << " ()))" << endl + << "return false;"; + } + + if (a.optional ()) + os << "}" + << "else" << endl + << "x." << epresent (a) << " (false);"; + + os << "}"; + } + }; + + + struct ElementData: Traversal::Element, Context + { + ElementData (Context& c) + : Context (c) + { + } + + virtual Void + traverse (SemanticGraph::Element& e) + { + // See also ChoiceParticleData. + // + String const& name (ename (e)); + + if (e.max () != 1) + { + if (exceptions) + os << "s >> x." << name << " ();"; + else + os << "if (!(s >> x." << name << " ()))" << endl + << "return false;"; + } + else + { + SemanticGraph::Type& t (e.type ()); + + Boolean fl (fixed_length (t)); + Boolean st (false); + + if (!fl) + { + StringType test (st); + test.dispatch (t); + } + + os << "{"; + + if (e.min () == 0) + { + os << "bool p;"; + + if (exceptions) + os << "s >> p;"; + else + os << endl + << "if (!(s >> p))" << endl + << "return false;"; + + os << endl + << "if (p)" + << "{"; + + if (fl) + os << "x." << epresent (e) << " (true);"; + } + + if (st) + { + // C-string requires special handling. + // + os << "char* i;"; + + if (exceptions) + os << "s >> i;"; + else + os << "if (!(s >> i))" << endl + << "return false;"; + + os << "x." << name << " (i);"; + } + else + { + if (!fl) + { + String fq (fq_name (t)); + + if (exceptions) + os << "x." << name << " (new " << fq << ");"; + else + os << fq << "* i = new " << fq << ";" + << endl + << "if (i == 0)" << endl + << "return false;" + << endl + << "x." << name << " (i);"; + } + + if (exceptions) + os << "s >> x." << name << " ();"; + else + os << "if (!(s >> x." << name << " ()))" << endl + << "return false;"; + } + + if (e.min () == 0) + os << "}" + << "else" << endl + << "x." << epresent (e) << " (false);"; + + os << "}"; + } + } + }; + + struct AllData: Traversal::All, Context + { + AllData (Context& c) + : Context (c) + { + } + + virtual Void + traverse (SemanticGraph::All& a) + { + // For the all compositor, maxOccurs=1 and minOccurs={0,1} + // and it can only contain particles. + // + if (a.min () == 0) + { + Boolean fl (fixed_length (a)); + + String const& name (ename (a)); + String const& present (epresent (a)); + + os << "{" + << "bool p;"; + + if (exceptions) + os << "s >> p;"; + else + os << endl + << "if (!(s >> p))" << endl + << "return false;"; + + os << endl + << "if (p)" + << "{"; + + if (fl) + os << "x." << present << " (true);"; + + if (!fl) + { + String fq (scope (a) + L"::" + etype (a)); + + if (exceptions) + os << "x." << name << " (new " << fq << ");"; + else + os << fq << "* i = new " << fq << ";" + << endl + << "if (i == 0)" << endl + << "return false;" + << endl + << "x." << name << " (i);"; + } + + if (exceptions) + os << "s >> x." << name << " ();"; + else + os << "if (!(s >> x." << name << " ()))" << endl + << "return false;"; + + os << "}" + << "else" << endl + << "x." << present << " (false);" + << "}"; + } + else + All::contains (a); + } + }; + + struct ChoiceParticleData: Traversal::Element, + Traversal::Compositor, + Context + { + ChoiceParticleData (Context& c) + : Context (c) + { + } + + virtual Void + traverse (SemanticGraph::Element& e) + { + os << "case " << scope (e) << "::" << etag (e) << ":" + << "{"; + + // Same as ElementData except that we don't need the extra scope. + // + String const& name (ename (e)); + + if (e.max () != 1) + { + if (exceptions) + os << "s >> x." << name << " ();"; + else + os << "if (!(s >> x." << name << " ()))" << endl + << "return false;"; + } + else + { + SemanticGraph::Type& t (e.type ()); + + Boolean fl (fixed_length (t)); + Boolean st (false); + + if (!fl) + { + StringType test (st); + test.dispatch (t); + } + + if (e.min () == 0) + { + os << "bool p;"; + + if (exceptions) + os << "s >> p;"; + else + os << endl + << "if (!(s >> p))" << endl + << "return false;"; + + os << endl + << "if (p)" + << "{"; + + if (fl) + os << "x." << epresent (e) << " (true);"; + } + + if (st) + { + // C-string requires special handling. + // + os << "char* i;"; + + if (exceptions) + os << "s >> i;"; + else + os << "if (!(s >> i))" << endl + << "return false;"; + + os << "x." << name << " (i);"; + } + else + { + if (!fl) + { + String fq (fq_name (t)); + + if (exceptions) + os << "x." << name << " (new " << fq << ");"; + else + os << fq << "* i = new " << fq << ";" + << endl + << "if (i == 0)" << endl + << "return false;" + << endl + << "x." << name << " (i);"; + } + + if (exceptions) + os << "s >> x." << name << " ();"; + else + os << "if (!(s >> x." << name << " ()))" << endl + << "return false;"; + } + + if (e.min () == 0) + os << "}" + << "else" << endl + << "x." << epresent (e) << " (false);"; + } + + os << "break;" + << "}"; + } + + virtual Void + traverse (SemanticGraph::Compositor& c) + { + os << "case " << scope (c) << "::" << etag (c) << ":" + << "{"; + + // A compositor in choice always results in a nested class. + // + String const& name (ename (c)); + + if (c.max () != 1) + { + String const& name (ename (c)); + + if (exceptions) + os << "s >> x." << name << " ();"; + else + os << "if (!(s >> x." << name << " ()))" << endl + << "return false;"; + } + else + { + Boolean fl (fixed_length (c)); + + if (c.min () == 0) + { + os << "bool p;"; + + if (exceptions) + os << "s >> p;"; + else + os << endl + << "if (!(s >> p))" << endl + << "return false;"; + + os << endl + << "if (p)" + << "{"; + + if (fl) + os << "x." << epresent (c) << " (true);"; + } + + if (!fl) + { + String fq (scope (c) + L"::" + etype (c)); + + if (exceptions) + os << "x." << name << " (new " << fq << ");"; + else + os << fq << "* i = new " << fq << ";" + << endl + << "if (i == 0)" << endl + << "return false;" + << endl + << "x." << name << " (i);"; + } + + if (exceptions) + os << "s >> x." << name << " ();"; + else + os << "if (!(s >> x." << name << " ()))" << endl + << "return false;"; + + if (c.min () == 0) + os << "}" + << "else" << endl + << "x." << epresent (c) << " (false);"; + } + + os << "break;" + << "}"; + } + }; + + struct ChoiceInSequenceData: Traversal::Choice, Context + { + ChoiceInSequenceData (Context& c) + : Context (c), particle_data_ (c) + { + contains_data_ >> particle_data_; + } + + virtual Void + traverse (SemanticGraph::Choice& c) + { + if (c.max () != 1) + { + String const& name (ename (c)); + + if (exceptions) + os << "s >> x." << name << " ();"; + else + os << "if (!(s >> x." << name << " ()))" << endl + << "return false;"; + } + else if (c.min () == 0) + { + Boolean fl (fixed_length (c)); + + String const& name (ename (c)); + String const& present (epresent (c)); + + os << "{" + << "bool p;"; + + if (exceptions) + os << "s >> p;"; + else + os << endl + << "if (!(s >> p))" << endl + << "return false;"; + + os << endl + << "if (p)" + << "{"; + + if (fl) + os << "x." << present << " (true);"; + + if (!fl) + { + String fq (scope (c) + L"::" + etype (c)); + + if (exceptions) + os << "x." << name << " (new " << fq << ");"; + else + os << fq << "* i = new " << fq << ";" + << endl + << "if (i == 0)" << endl + << "return false;" + << endl + << "x." << name << " (i);"; + } + + if (exceptions) + os << "s >> x." << name << " ();"; + else + os << "if (!(s >> x." << name << " ()))" << endl + << "return false;"; + + os << "}" + << "else" << endl + << "x." << present << " (false);" + << "}"; + } + else + { + String const& arm (earm (c)); + + os << "{" + << "unsigned int i;"; + + if (exceptions) + os << "s >> i;"; + else + os << "if (!(s >> i))" << endl + << "return false;"; + + os << "x." << arm << " (static_cast< " << scope (c) << "::" << + earm_tag (c) << " > (i));"; + + os << "switch (x." << arm << " ())" + << "{"; + + Choice::contains (c, contains_data_); + + os << "default:" << endl + << "break;" + << "}" + << "}"; + } + } + + private: + ChoiceParticleData particle_data_; + Traversal::ContainsParticle contains_data_; + }; + + struct SequenceInSequenceData: Traversal::Sequence, Context + { + SequenceInSequenceData (Context& c) + : Context (c) + { + } + + virtual Void + traverse (SemanticGraph::Sequence& s) + { + if (s.max () != 1) + { + String const& name (ename (s)); + + if (exceptions) + os << "s >> x." << name << " ();"; + else + os << "if (!(s >> x." << name << " ()))" << endl + << "return false;"; + } + else if (s.min () == 0) + { + Boolean fl (fixed_length (s)); + + String const& name (ename (s)); + String const& present (epresent (s)); + + os << "{" + << "bool p;"; + + if (exceptions) + os << "s >> p;"; + else + os << endl + << "if (!(s >> p))" << endl + << "return false;"; + + os << endl + << "if (p)" + << "{"; + + if (fl) + os << "x." << present << " (true);"; + + if (!fl) + { + String fq (scope (s) + L"::" + etype (s)); + + if (exceptions) + os << "x." << name << " (new " << fq << ");"; + else + os << fq << "* i = new " << fq << ";" + << endl + << "if (i == 0)" << endl + << "return false;" + << endl + << "x." << name << " (i);"; + } + + if (exceptions) + os << "s >> x." << name << " ();"; + else + os << "if (!(s >> x." << name << " ()))" << endl + << "return false;"; + + os << "}" + << "else" << endl + << "x." << present << " (false);" + << "}"; + } + else + Sequence::contains (s); + } + }; + + // + // Nested classes. + // + + struct All: Traversal::All, Context + { + All (Context& c, Traversal::ContainsParticle& contains_data) + : Context (c), contains_data_ (contains_data) + { + } + + virtual Void + traverse (SemanticGraph::All& a) + { + // For the all compositor, maxOccurs=1 and minOccurs={0,1} + // and it can only contain particles. + // + if (a.min () == 0) + { + String const& type (etype (a)); + String const& scope (Context::scope (a)); + + for (Streams::ConstIterator i (istreams.begin ()); + i != istreams.end (); ++i) + { + os << (exceptions ? "void" : "bool") << endl + << "operator>> (" << istream (*i) << "& s," << endl + << scope << "::" << type << "& x)" + << "{" + << "XSDE_UNUSED (s);" + << "XSDE_UNUSED (x);" + << endl; + + All::contains (a, contains_data_); + + os << (exceptions ? "" : "return true;") + << "}"; + } + } + } + + private: + Traversal::ContainsParticle& contains_data_; + }; + + struct Choice: Traversal::Choice, Context + { + Choice (Context& c, Boolean in_choice) + : Context (c), in_choice_ (in_choice), particle_data_ (c) + { + contains_data_ >> particle_data_; + } + + virtual Void + traverse (SemanticGraph::Choice& c) + { + // When choice is in choice we generate nested class even + // for min == max == 1. + // + if (in_choice_ || c.max () != 1 || c.min () == 0) + { + String const& arm (earm (c)); + String const& type (etype (c)); + String const& scope (Context::scope (c)); + + for (Streams::ConstIterator i (istreams.begin ()); + i != istreams.end (); ++i) + { + os << (exceptions ? "void" : "bool") << endl + << "operator>> (" << istream (*i) << "& s," << endl + << scope << "::" << type << "& x)" + << "{" + << "XSDE_UNUSED (s);" + << endl + << "unsigned int i;"; + + if (exceptions) + os << "s >> i;"; + else + os << "if (!(s >> i))" << endl + << "return false;"; + + os << "x." << arm << " (static_cast< " << scope << "::" << + type << "::" << earm_tag (c) << " > (i));"; + + os << "switch (x." << arm << " ())" + << "{"; + + Choice::contains (c, contains_data_); + + os << "default:" << endl + << "break;" + << "}" + << (exceptions ? "" : "return true;") + << "}"; + } + } + + Choice::contains (c); + } + + private: + Boolean in_choice_; + + ChoiceParticleData particle_data_; + Traversal::ContainsParticle contains_data_; + }; + + + struct Sequence: Traversal::Sequence, Context + { + Sequence (Context& c, + Boolean in_choice, + Traversal::ContainsParticle& contains_data) + : Context (c), + in_choice_ (in_choice), + contains_data_ (contains_data) + { + } + + virtual Void + traverse (SemanticGraph::Sequence& s) + { + // When sequence is in choice we generate nested class even + // for min == max == 1. + // + if (in_choice_ || s.max () != 1 || s.min () == 0) + { + String const& type (etype (s)); + String const& scope (Context::scope (s)); + + for (Streams::ConstIterator i (istreams.begin ()); + i != istreams.end (); ++i) + { + os << (exceptions ? "void" : "bool") << endl + << "operator>> (" << istream (*i) << "& s," << endl + << scope << "::" << type << "& x)" + << "{" + << "XSDE_UNUSED (s);" + << "XSDE_UNUSED (x);" + << endl; + + Sequence::contains (s, contains_data_); + + os << (exceptions ? "" : "return true;") + << "}"; + } + } + + Sequence::contains (s); + } + + private: + Boolean in_choice_; + Traversal::ContainsParticle& contains_data_; + }; + + struct Complex : Traversal::Complex, Context + { + Complex (Context& c) + : Context (c), + + // Use ret instead of base to get auto-conversion + // for fundamental types from the wrappers. + // + base_name_ (c, TypeName::ret), + + // Data + // + attribute_data_ (c), + element_data_ (c), + all_data_ (c), + choice_in_sequence_data_ (c), + sequence_in_sequence_data_ (c), + + // Nested classes. + // + all_ (c, all_contains_data_), + choice_in_choice_ (c, true), + choice_in_sequence_ (c, false), + sequence_in_choice_ (c, true, sequence_contains_data_), + sequence_in_sequence_ (c, false, sequence_contains_data_) + { + // Data. + // + attribute_names_data_ >> attribute_data_; + + all_data_ >> all_contains_data_ >> element_data_; + + sequence_in_sequence_data_ >> sequence_contains_data_; + sequence_contains_data_ >> element_data_; + sequence_contains_data_ >> choice_in_sequence_data_; + sequence_contains_data_ >> sequence_in_sequence_data_; + + contains_compositor_data_ >> all_data_; + contains_compositor_data_ >> choice_in_sequence_data_; + contains_compositor_data_ >> sequence_in_sequence_data_; + + // Nested classes. + // + all_ >> all_contains_; + + choice_in_choice_ >> choice_contains_; + choice_in_sequence_ >> choice_contains_; + choice_contains_ >> choice_in_choice_; + choice_contains_ >> sequence_in_choice_; + + sequence_in_choice_ >> sequence_contains_; + sequence_in_sequence_ >> sequence_contains_; + sequence_contains_ >> choice_in_sequence_; + sequence_contains_ >> sequence_in_sequence_; + + contains_compositor_ >> all_; + contains_compositor_ >> choice_in_sequence_; + contains_compositor_ >> sequence_in_sequence_; + } + + virtual Void + traverse (Type& c) + { + Boolean restriction (restriction_p (c)); + + String name (ename (c)); + + for (Streams::ConstIterator i (istreams.begin ()); + i != istreams.end (); ++i) + { + os << (exceptions ? "void" : "bool") << endl + << "operator>> (" << istream (*i) << "& s," << endl + << name << "& x)" + << "{" + << "XSDE_UNUSED (s);" + << "XSDE_UNUSED (x);" + << endl; + + if (c.inherits_p ()) + { + SemanticGraph::Type& b (c.inherits ().base ()); + + Boolean c_str (false); + + if (!stl) + { + StringType test (c_str); + test.dispatch (b); + } + + // Special handling for C-string base. + // + if (c_str) + { + os << "char* b;"; + + if (exceptions) + os << "s >> b;"; + else + os << "if (!(s >> b))" << endl + << "return false;" + << endl; + + os << "x.base_value (b);" + << endl; + } + else + { + base_name_.dispatch (b); + os << " b = x;"; + + if (exceptions) + os << "s >> b;"; + else + os << "if (!(s >> b))" << endl + << "return false;" + << endl; + } + } + + if (!restriction) + { + Complex::names (c, attribute_names_data_); + + if (c.contains_compositor_p ()) + Complex::contains_compositor (c, contains_compositor_data_); + } + + os << (exceptions ? "" : "return true;") + << "}"; + } + + // Operators for nested classes. + // + if (!restriction && c.contains_compositor_p ()) + Complex::contains_compositor (c, contains_compositor_); + } + + private: + TypeName base_name_; + + // Data. + // + AttributeData attribute_data_; + Traversal::Names attribute_names_data_; + + ElementData element_data_; + AllData all_data_; + ChoiceInSequenceData choice_in_sequence_data_; + SequenceInSequenceData sequence_in_sequence_data_; + Traversal::ContainsParticle all_contains_data_; + Traversal::ContainsParticle sequence_contains_data_; + + Traversal::ContainsCompositor contains_compositor_data_; + + // Nested classes. + // + All all_; + Choice choice_in_choice_; + Choice choice_in_sequence_; + Sequence sequence_in_choice_; + Sequence sequence_in_sequence_; + Traversal::ContainsParticle all_contains_; + Traversal::ContainsParticle choice_contains_; + Traversal::ContainsParticle sequence_contains_; + + Traversal::ContainsCompositor contains_compositor_; + }; + } + + Void + generate_extraction_source (Context& ctx) + { + Traversal::Schema schema; + Traversal::Sources sources; + Traversal::Names names_ns, names; + + Namespace ns (ctx); + + List list (ctx); + Union union_ (ctx); + Complex complex (ctx); + + schema >> sources >> schema; + schema >> names_ns >> ns >> names; + + names >> list; + names >> union_; + names >> complex; + + schema.dispatch (ctx.schema_root); + } + } +} diff --git a/xsde/cxx/hybrid/extraction-source.hxx b/xsde/cxx/hybrid/extraction-source.hxx new file mode 100644 index 0000000..ee65b3e --- /dev/null +++ b/xsde/cxx/hybrid/extraction-source.hxx @@ -0,0 +1,22 @@ +// file : xsde/cxx/hybrid/extraction-source.hxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#ifndef CXX_HYBRID_EXTRACTION_SOURCE_HXX +#define CXX_HYBRID_EXTRACTION_SOURCE_HXX + +#include + +#include + +namespace CXX +{ + namespace Hybrid + { + Void + generate_extraction_source (Context&); + } +} + +#endif // CXX_HYBRID_EXTRACTION_SOURCE_HXX diff --git a/xsde/cxx/hybrid/generator.cxx b/xsde/cxx/hybrid/generator.cxx index b6215f9..495e649 100644 --- a/xsde/cxx/hybrid/generator.cxx +++ b/xsde/cxx/hybrid/generator.cxx @@ -11,13 +11,17 @@ #include #include - #include #include #include #include #include +#include +#include +#include +#include + #include #include #include @@ -117,6 +121,8 @@ namespace CXX extern Key suppress_validation = "suppress-validation"; extern Key suppress_parser_val = "suppress-parser-val"; extern Key suppress_serializer_val = "suppress-serializer-val"; + extern Key generate_insertion = "generate-insertion"; + extern Key generate_extraction = "generate-extraction"; extern Key generate_inline = "generate-inline"; extern Key generate_forward = "generate-forward"; extern Key generate_xml_schema = "generate-xml-schema"; @@ -238,6 +244,16 @@ namespace CXX << " serializer." << endl; + e << "--generate-insertion " << endl + << " Generate data representation stream insertion\n" + << " operators for the output stream type." + << endl; + + e << "--generate-extraction " << endl + << " Generate data representation stream extraction\n" + << " operators for the input stream type." + << endl; + e << "--generate-inline" << endl << " Generate certain functions inline." << endl; @@ -1491,6 +1507,12 @@ namespace CXX generate_tree_forward (ctx, false); generate_tree_header (ctx); + + if (!ops.value ().empty ()) + generate_insertion_header (ctx); + + if (!ops.value ().empty ()) + generate_extraction_header (ctx); } else generate_tree_forward (ctx, true); @@ -1650,6 +1672,12 @@ namespace CXX generate_tree_source (ctx); + if (!ops.value ().empty ()) + generate_insertion_source (ctx); + + if (!ops.value ().empty ()) + generate_extraction_source (ctx); + cxx << "#include " << endl << endl; } diff --git a/xsde/cxx/hybrid/insertion-header.cxx b/xsde/cxx/hybrid/insertion-header.cxx new file mode 100644 index 0000000..050b58f --- /dev/null +++ b/xsde/cxx/hybrid/insertion-header.cxx @@ -0,0 +1,255 @@ +// file : xsd/cxx/hybrid/insertion-header.cxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#include + +#include +#include + +namespace CXX +{ + namespace Hybrid + { + namespace + { + struct List : Traversal::List, Context + { + List (Context& c) + : Context (c) + { + } + + virtual Void + traverse (Type& l) + { + String name (ename (l)); + + for (Streams::ConstIterator i (ostreams.begin ()); + i != ostreams.end (); ++i) + { + os << (exceptions ? "void" : "bool") << endl + << "operator<< (" << ostream (*i) << "&," << endl + << "const " << name << "&);" + << endl; + } + } + }; + + struct Union : Traversal::Union, Context + { + Union (Context& c) + : Context (c) + { + } + + virtual Void + traverse (Type& u) + { + String name (ename (u)); + + for (Streams::ConstIterator i (ostreams.begin ()); + i != ostreams.end (); ++i) + { + os << (exceptions ? "void" : "bool") << endl + << "operator<< (" << ostream (*i) << "&," << endl + << "const " << name << "&);" + << endl; + } + } + }; + + // + // Nested classes. + // + + struct All: Traversal::All, Context + { + All (Context& c) + : Context (c) + { + } + + virtual Void + traverse (SemanticGraph::All& a) + { + // For the all compositor, maxOccurs=1 and minOccurs={0,1} + // and it can only contain particles. + // + if (a.min () == 0) + { + String const& type (etype (a)); + String const& scope (Context::scope (a)); + + for (Streams::ConstIterator i (ostreams.begin ()); + i != ostreams.end (); ++i) + { + os << (exceptions ? "void" : "bool") << endl + << "operator<< (" << ostream (*i) << "&," << endl + << "const " << scope << "::" << type << "&);" + << endl; + } + } + } + }; + + struct Choice: Traversal::Choice, Context + { + Choice (Context& c, Boolean in_choice) + : Context (c), in_choice_ (in_choice) + { + } + + virtual Void + traverse (SemanticGraph::Choice& c) + { + // When choice is in choice we generate nested class even + // for min == max == 1. + // + if (in_choice_ || c.max () != 1 || c.min () == 0) + { + String const& type (etype (c)); + String const& scope (Context::scope (c)); + + for (Streams::ConstIterator i (ostreams.begin ()); + i != ostreams.end (); ++i) + { + os << (exceptions ? "void" : "bool") << endl + << "operator<< (" << ostream (*i) << "&," << endl + << "const " << scope << "::" << type << "&);" + << endl; + } + } + + Choice::contains (c); + } + + private: + Boolean in_choice_; + }; + + + struct Sequence: Traversal::Sequence, Context + { + Sequence (Context& c, Boolean in_choice) + : Context (c), in_choice_ (in_choice) + { + } + + virtual Void + traverse (SemanticGraph::Sequence& s) + { + // When sequence is in choice we generate nested class even + // for min == max == 1. + // + if (in_choice_ || s.max () != 1 || s.min () == 0) + { + String const& type (etype (s)); + String const& scope (Context::scope (s)); + + for (Streams::ConstIterator i (ostreams.begin ()); + i != ostreams.end (); ++i) + { + os << (exceptions ? "void" : "bool") << endl + << "operator<< (" << ostream (*i) << "&," << endl + << "const " << scope << "::" << type << "&);" + << endl; + } + } + + Sequence::contains (s); + } + + private: + Boolean in_choice_; + }; + + struct Complex : Traversal::Complex, Context + { + Complex (Context& c) + : Context (c), + all_ (c), + choice_in_choice_ (c, true), + choice_in_sequence_ (c, false), + sequence_in_choice_ (c, true), + sequence_in_sequence_ (c, false) + { + all_ >> all_contains_; + + choice_in_choice_ >> choice_contains_; + choice_in_sequence_ >> choice_contains_; + choice_contains_ >> choice_in_choice_; + choice_contains_ >> sequence_in_choice_; + + sequence_in_choice_ >> sequence_contains_; + sequence_in_sequence_ >> sequence_contains_; + sequence_contains_ >> choice_in_sequence_; + sequence_contains_ >> sequence_in_sequence_; + + contains_compositor_ >> all_; + contains_compositor_ >> choice_in_sequence_; + contains_compositor_ >> sequence_in_sequence_; + } + + virtual Void + traverse (Type& c) + { + if (!restriction_p (c)) + { + String name (ename (c)); + + for (Streams::ConstIterator i (ostreams.begin ()); + i != ostreams.end (); ++i) + { + os << (exceptions ? "void" : "bool") << endl + << "operator<< (" << ostream (*i) << "&," << endl + << "const " << name << "&);" + << endl; + } + + // Operators for nested classes. + // + if (c.contains_compositor_p ()) + Complex::contains_compositor (c, contains_compositor_); + } + } + + private: + All all_; + Choice choice_in_choice_; + Choice choice_in_sequence_; + Sequence sequence_in_choice_; + Sequence sequence_in_sequence_; + Traversal::ContainsParticle all_contains_; + Traversal::ContainsParticle choice_contains_; + Traversal::ContainsParticle sequence_contains_; + + Traversal::ContainsCompositor contains_compositor_; + }; + } + + Void + generate_insertion_header (Context& ctx) + { + Traversal::Schema schema; + Traversal::Sources sources; + Traversal::Names names_ns, names; + + Namespace ns (ctx); + + List list (ctx); + Union union_ (ctx); + Complex complex (ctx); + + schema >> sources >> schema; + schema >> names_ns >> ns >> names; + + names >> list; + names >> union_; + names >> complex; + + schema.dispatch (ctx.schema_root); + } + } +} diff --git a/xsde/cxx/hybrid/insertion-header.hxx b/xsde/cxx/hybrid/insertion-header.hxx new file mode 100644 index 0000000..8f17968 --- /dev/null +++ b/xsde/cxx/hybrid/insertion-header.hxx @@ -0,0 +1,22 @@ +// file : xsde/cxx/hybrid/insertion-header.hxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#ifndef CXX_HYBRID_INSERTION_HEADER_HXX +#define CXX_HYBRID_INSERTION_HEADER_HXX + +#include + +#include + +namespace CXX +{ + namespace Hybrid + { + Void + generate_insertion_header (Context&); + } +} + +#endif // CXX_HYBRID_INSERTION_HEADER_HXX diff --git a/xsde/cxx/hybrid/insertion-source.cxx b/xsde/cxx/hybrid/insertion-source.cxx new file mode 100644 index 0000000..58fe9f5 --- /dev/null +++ b/xsde/cxx/hybrid/insertion-source.cxx @@ -0,0 +1,694 @@ +// file : xsd/cxx/hybrid/insertion-source.cxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#include + +#include +#include + +namespace CXX +{ + namespace Hybrid + { + namespace + { + struct List : Traversal::List, Context + { + List (Context& c) + : Context (c), base_name_ (c, TypeName::seq) + { + } + + virtual Void + traverse (Type& l) + { + String name (ename (l)); + + for (Streams::ConstIterator i (ostreams.begin ()); + i != ostreams.end (); ++i) + { + os << (exceptions ? "void" : "bool") << endl + << "operator<< (" << ostream (*i) << "& s," << endl + << "const " << name << "& x)" + << "{" + << "const "; + + base_name_.dispatch (l.argumented ().type ()); + + os << "& b = x;" + << (exceptions ? "" : "return ") << "s << b;" + << "}"; + } + } + + private: + TypeName base_name_; + }; + + struct Union : Traversal::Union, Context + { + Union (Context& c) + : Context (c) + { + } + + virtual Void + traverse (Type& u) + { + String name (ename (u)); + String const& value (u.context ().get ("value")); + + for (Streams::ConstIterator i (ostreams.begin ()); + i != ostreams.end (); ++i) + { + os << (exceptions ? "void" : "bool") << endl + << "operator<< (" << ostream (*i) << "& s," << endl + << "const " << name << "& x)" + << "{" + << (exceptions ? "" : "return ") << "s << x." << value << " ();" + << "}"; + } + } + }; + + // + // Data. + // + + struct AttributeData: Traversal::Attribute, Context + { + AttributeData (Context& c) + : Context (c) + { + } + + virtual Void + traverse (SemanticGraph::Attribute& a) + { + if (a.optional ()) + { + String const& present (epresent (a)); + + if (exceptions) + os << "s << x." << present << " ();"; + else + os << "if (!(s << x." << present << " ()))" << endl + << "return false;"; + + os << endl + << "if (x." << present << " ())" + << "{"; + } + + String const& name (ename (a)); + + if (exceptions) + os << "s << x." << name << " ();"; + else + os << "if (!(s << x." << name << " ()))" << endl + << "return false;"; + + if (a.optional ()) + os << "}"; + } + }; + + + struct ElementData: Traversal::Element, Context + { + ElementData (Context& c) + : Context (c) + { + } + + virtual Void + traverse (SemanticGraph::Element& e) + { + if (e.max () == 1 && e.min () == 0) + { + String const& present (epresent (e)); + + if (exceptions) + os << "s << x." << present << " ();"; + else + os << "if (!(s << x." << present << " ()))" << endl + << "return false;"; + + os << endl + << "if (x." << present << " ())" + << "{"; + } + + String const& name (ename (e)); + + if (exceptions) + os << "s << x." << name << " ();"; + else + os << "if (!(s << x." << name << " ()))" << endl + << "return false;"; + + if (e.max () == 1 && e.min () == 0) + os << "}"; + } + }; + + struct AllData: Traversal::All, Context + { + AllData (Context& c) + : Context (c) + { + } + + virtual Void + traverse (SemanticGraph::All& a) + { + // For the all compositor, maxOccurs=1 and minOccurs={0,1} + // and it can only contain particles. + // + if (a.min () == 0) + { + String const& name (ename (a)); + String const& present (epresent (a)); + + if (exceptions) + os << "s << x." << present << " ();"; + else + os << "if (!(s << x." << present << " ()))" << endl + << "return false;"; + + os << endl + << "if (x." << present << " ())" + << "{"; + + if (exceptions) + os << "s << x." << name << " ();"; + else + os << "if (!(s << x." << name << " ()))" << endl + << "return false;"; + + os << "}"; + } + else + All::contains (a); + } + }; + + struct ChoiceParticleData: ElementData, + Traversal::Compositor + { + ChoiceParticleData (Context& c) + : ElementData (c) + { + } + + virtual Void + traverse (SemanticGraph::Element& e) + { + os << "case " << scope (e) << "::" << etag (e) << ":" + << "{"; + + ElementData::traverse (e); + + os << "break;" + << "}"; + } + + virtual Void + traverse (SemanticGraph::Compositor& c) + { + os << "case " << scope (c) << "::" << etag (c) << ":" + << "{"; + + // A compositor in choice always results in a nested class. + // + if (c.max () == 1 && c.min () == 0) + { + String const& present (epresent (c)); + + if (exceptions) + os << "s << x." << present << " ();"; + else + os << "if (!(s << x." << present << " ()))" << endl + << "return false;"; + + os << endl + << "if (x." << present << " ())" + << "{"; + } + + String const& name (ename (c)); + + if (exceptions) + os << "s << x." << name << " ();"; + else + os << "if (!(s << x." << name << " ()))" << endl + << "return false;"; + + if (c.max () == 1 && c.min () == 0) + os << "}"; + + os << "break;" + << "}"; + } + }; + + struct ChoiceInSequenceData: Traversal::Choice, Context + { + ChoiceInSequenceData (Context& c) + : Context (c), particle_data_ (c) + { + contains_data_ >> particle_data_; + } + + virtual Void + traverse (SemanticGraph::Choice& c) + { + if (c.max () != 1) + { + String const& name (ename (c)); + + if (exceptions) + os << "s << x." << name << " ();"; + else + os << "if (!(s << x." << name << " ()))" << endl + << "return false;"; + } + else if (c.min () == 0) + { + String const& name (ename (c)); + String const& present (epresent (c)); + + if (exceptions) + os << "s << x." << present << " ();"; + else + os << "if (!(s << x." << present << " ()))" << endl + << "return false;"; + + os << endl + << "if (x." << present << " ())" + << "{"; + + if (exceptions) + os << "s << x." << name << " ();"; + else + os << "if (!(s << x." << name << " ()))" << endl + << "return false;"; + + os << "}"; + } + else + { + String const& arm (earm (c)); + + if (exceptions) + os << "s << static_cast< unsigned int > (x." << arm << " ());"; + else + os << "if (!(s << static_cast< unsigned int > (x." << + arm << " ())))" << endl + << "return false;"; + + os << "switch (x." << arm << " ())" + << "{"; + + Choice::contains (c, contains_data_); + + os << "default:" << endl + << "break;" + << "}"; + } + } + + private: + ChoiceParticleData particle_data_; + Traversal::ContainsParticle contains_data_; + }; + + struct SequenceInSequenceData: Traversal::Sequence, Context + { + SequenceInSequenceData (Context& c) + : Context (c) + { + } + + virtual Void + traverse (SemanticGraph::Sequence& s) + { + if (s.max () != 1) + { + String const& name (ename (s)); + + if (exceptions) + os << "s << x." << name << " ();"; + else + os << "if (!(s << x." << name << " ()))" << endl + << "return false;"; + } + else if (s.min () == 0) + { + String const& name (ename (s)); + String const& present (epresent (s)); + + if (exceptions) + os << "s << x." << present << " ();"; + else + os << "if (!(s << x." << present << " ()))" << endl + << "return false;"; + + os << endl + << "if (x." << present << " ())" + << "{"; + + if (exceptions) + os << "s << x." << name << " ();"; + else + os << "if (!(s << x." << name << " ()))" << endl + << "return false;"; + + os << "}"; + } + else + Sequence::contains (s); + } + }; + + // + // Nested classes. + // + + struct All: Traversal::All, Context + { + All (Context& c, Traversal::ContainsParticle& contains_data) + : Context (c), contains_data_ (contains_data) + { + } + + virtual Void + traverse (SemanticGraph::All& a) + { + // For the all compositor, maxOccurs=1 and minOccurs={0,1} + // and it can only contain particles. + // + if (a.min () == 0) + { + String const& type (etype (a)); + String const& scope (Context::scope (a)); + + for (Streams::ConstIterator i (ostreams.begin ()); + i != ostreams.end (); ++i) + { + os << (exceptions ? "void" : "bool") << endl + << "operator<< (" << ostream (*i) << "& s," << endl + << "const " << scope << "::" << type << "& x)" + << "{" + << "XSDE_UNUSED (s);" + << "XSDE_UNUSED (x);" + << endl; + + All::contains (a, contains_data_); + + os << (exceptions ? "" : "return true;") + << "}"; + } + } + } + + private: + Traversal::ContainsParticle& contains_data_; + }; + + struct Choice: Traversal::Choice, Context + { + Choice (Context& c, Boolean in_choice) + : Context (c), in_choice_ (in_choice), particle_data_ (c) + { + contains_data_ >> particle_data_; + } + + virtual Void + traverse (SemanticGraph::Choice& c) + { + // When choice is in choice we generate nested class even + // for min == max == 1. + // + if (in_choice_ || c.max () != 1 || c.min () == 0) + { + String const& arm (earm (c)); + String const& type (etype (c)); + String const& scope (Context::scope (c)); + + for (Streams::ConstIterator i (ostreams.begin ()); + i != ostreams.end (); ++i) + { + os << (exceptions ? "void" : "bool") << endl + << "operator<< (" << ostream (*i) << "& s," << endl + << "const " << scope << "::" << type << "& x)" + << "{" + << "XSDE_UNUSED (s);" + << endl; + + if (exceptions) + os << "s << static_cast< unsigned int > (x." << arm << " ());"; + else + os << "if (!(s << static_cast< unsigned int > (x." << + arm << " ())))" << endl + << "return false;"; + + os << "switch (x." << earm (c) << " ())" + << "{"; + + Choice::contains (c, contains_data_); + + os << "default:" << endl + << "break;" + << "}" + << (exceptions ? "" : "return true;") + << "}"; + } + } + + Choice::contains (c); + } + + private: + Boolean in_choice_; + + ChoiceParticleData particle_data_; + Traversal::ContainsParticle contains_data_; + }; + + + struct Sequence: Traversal::Sequence, Context + { + Sequence (Context& c, + Boolean in_choice, + Traversal::ContainsParticle& contains_data) + : Context (c), + in_choice_ (in_choice), + contains_data_ (contains_data) + { + } + + virtual Void + traverse (SemanticGraph::Sequence& s) + { + // When sequence is in choice we generate nested class even + // for min == max == 1. + // + if (in_choice_ || s.max () != 1 || s.min () == 0) + { + String const& type (etype (s)); + String const& scope (Context::scope (s)); + + for (Streams::ConstIterator i (ostreams.begin ()); + i != ostreams.end (); ++i) + { + os << (exceptions ? "void" : "bool") << endl + << "operator<< (" << ostream (*i) << "& s," << endl + << "const " << scope << "::" << type << "& x)" + << "{" + << "XSDE_UNUSED (s);" + << "XSDE_UNUSED (x);" + << endl; + + Sequence::contains (s, contains_data_); + + os << (exceptions ? "" : "return true;") + << "}"; + } + } + + Sequence::contains (s); + } + + private: + Boolean in_choice_; + Traversal::ContainsParticle& contains_data_; + }; + + struct Complex : Traversal::Complex, Context + { + Complex (Context& c) + : Context (c), + + // Use ro_ret instead of base to get auto-conversion + // for fundamental types from the wrappers. + // + base_name_ (c, TypeName::ro_ret), + + // Data + // + attribute_data_ (c), + element_data_ (c), + all_data_ (c), + choice_in_sequence_data_ (c), + sequence_in_sequence_data_ (c), + + // Nested classes. + // + all_ (c, all_contains_data_), + choice_in_choice_ (c, true), + choice_in_sequence_ (c, false), + sequence_in_choice_ (c, true, sequence_contains_data_), + sequence_in_sequence_ (c, false, sequence_contains_data_) + { + // Data. + // + attribute_names_data_ >> attribute_data_; + + all_data_ >> all_contains_data_ >> element_data_; + + sequence_in_sequence_data_ >> sequence_contains_data_; + sequence_contains_data_ >> element_data_; + sequence_contains_data_ >> choice_in_sequence_data_; + sequence_contains_data_ >> sequence_in_sequence_data_; + + contains_compositor_data_ >> all_data_; + contains_compositor_data_ >> choice_in_sequence_data_; + contains_compositor_data_ >> sequence_in_sequence_data_; + + // Nested classes. + // + all_ >> all_contains_; + + choice_in_choice_ >> choice_contains_; + choice_in_sequence_ >> choice_contains_; + choice_contains_ >> choice_in_choice_; + choice_contains_ >> sequence_in_choice_; + + sequence_in_choice_ >> sequence_contains_; + sequence_in_sequence_ >> sequence_contains_; + sequence_contains_ >> choice_in_sequence_; + sequence_contains_ >> sequence_in_sequence_; + + contains_compositor_ >> all_; + contains_compositor_ >> choice_in_sequence_; + contains_compositor_ >> sequence_in_sequence_; + } + + virtual Void + traverse (Type& c) + { + Boolean restriction (restriction_p (c)); + + String name (ename (c)); + + for (Streams::ConstIterator i (ostreams.begin ()); + i != ostreams.end (); ++i) + { + os << (exceptions ? "void" : "bool") << endl + << "operator<< (" << ostream (*i) << "& s," << endl + << "const " << name << "& x)" + << "{" + << "XSDE_UNUSED (s);" + << "XSDE_UNUSED (x);" + << endl; + + if (c.inherits_p ()) + { + base_name_.dispatch (c.inherits ().base ()); + os << " b = x;"; + + if (exceptions) + os << "s << b;"; + else + os << "if (!(s << b))" << endl + << "return false;" + << endl; + } + + if (!restriction) + { + Complex::names (c, attribute_names_data_); + + if (c.contains_compositor_p ()) + Complex::contains_compositor (c, contains_compositor_data_); + } + + os << (exceptions ? "" : "return true;") + << "}"; + } + + // Operators for nested classes. + // + if (!restriction && c.contains_compositor_p ()) + Complex::contains_compositor (c, contains_compositor_); + } + + private: + TypeName base_name_; + + // Data. + // + AttributeData attribute_data_; + Traversal::Names attribute_names_data_; + + ElementData element_data_; + AllData all_data_; + ChoiceInSequenceData choice_in_sequence_data_; + SequenceInSequenceData sequence_in_sequence_data_; + Traversal::ContainsParticle all_contains_data_; + Traversal::ContainsParticle sequence_contains_data_; + + Traversal::ContainsCompositor contains_compositor_data_; + + // Nested classes. + // + All all_; + Choice choice_in_choice_; + Choice choice_in_sequence_; + Sequence sequence_in_choice_; + Sequence sequence_in_sequence_; + Traversal::ContainsParticle all_contains_; + Traversal::ContainsParticle choice_contains_; + Traversal::ContainsParticle sequence_contains_; + + Traversal::ContainsCompositor contains_compositor_; + }; + } + + Void + generate_insertion_source (Context& ctx) + { + Traversal::Schema schema; + Traversal::Sources sources; + Traversal::Names names_ns, names; + + Namespace ns (ctx); + + List list (ctx); + Union union_ (ctx); + Complex complex (ctx); + + schema >> sources >> schema; + schema >> names_ns >> ns >> names; + + names >> list; + names >> union_; + names >> complex; + + schema.dispatch (ctx.schema_root); + } + } +} diff --git a/xsde/cxx/hybrid/insertion-source.hxx b/xsde/cxx/hybrid/insertion-source.hxx new file mode 100644 index 0000000..fe6463c --- /dev/null +++ b/xsde/cxx/hybrid/insertion-source.hxx @@ -0,0 +1,22 @@ +// file : xsde/cxx/hybrid/insertion-source.hxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#ifndef CXX_HYBRID_INSERTION_SOURCE_HXX +#define CXX_HYBRID_INSERTION_SOURCE_HXX + +#include + +#include + +namespace CXX +{ + namespace Hybrid + { + Void + generate_insertion_source (Context&); + } +} + +#endif // CXX_HYBRID_INSERTION_SOURCE_HXX diff --git a/xsde/cxx/hybrid/tree-forward.cxx b/xsde/cxx/hybrid/tree-forward.cxx index f1c0dfa..32f1180 100644 --- a/xsde/cxx/hybrid/tree-forward.cxx +++ b/xsde/cxx/hybrid/tree-forward.cxx @@ -415,6 +415,7 @@ namespace CXX virtual Void traverse (SemanticGraph::Fundamental::Base64Binary&) { + gen_using ("::xsde::cxx::buffer"); gen_typedef ("base64_binary", "::xsde::cxx::buffer"); } @@ -431,6 +432,7 @@ namespace CXX virtual Void traverse (SemanticGraph::Fundamental::Date&) { + gen_using ("::xsde::cxx::time_zone"); gen_using ("::xsde::cxx::date"); } @@ -534,6 +536,66 @@ namespace CXX << "using ::xsde::cxx::strndupx;"; } + // sequences + // + os << endl + << "using ::xsde::cxx::hybrid::pod_seq;" + << "using ::xsde::cxx::hybrid::fix_seq;" + << "using ::xsde::cxx::hybrid::var_seq;" + << "using ::xsde::cxx::hybrid::str_seq;" + << "using ::xsde::cxx::hybrid::data_seq;"; + + // Data representation stream types. + // + Boolean icdr (false), ocdr (false); + Boolean ixdr (false), oxdr (false); + + for (Streams::ConstIterator i (istreams.begin ()); + i != istreams.end (); ++i) + { + if (*i == "CDR") + icdr = true; + else if (*i == "XDR") + ixdr = true; + } + + for (Streams::ConstIterator i (ostreams.begin ()); + i != ostreams.end (); ++i) + { + if (*i == "CDR") + ocdr = true; + else if (*i == "XDR") + oxdr = true; + } + + if (icdr || ocdr) + { + os << endl; + + if (exceptions) + os << "using ::xsde::cxx::hybrid::cdr_exception;"; + + if (icdr) + os << "using ::xsde::cxx::hybrid::icdrstream;"; + + if (ocdr) + os << "using ::xsde::cxx::hybrid::ocdrstream;"; + } + + if (ixdr || oxdr) + { + os << endl; + + if (exceptions) + os << "using ::xsde::cxx::hybrid::xdr_exception;"; + + if (ixdr) + os << "using ::xsde::cxx::hybrid::ixdrstream;"; + + if (oxdr) + os << "using ::xsde::cxx::hybrid::oxdrstream;"; + } + post (ns); } }; @@ -561,8 +623,33 @@ namespace CXX ctx.os << "#include " << endl; ctx.os << "#include " << endl + << "#include " << endl << endl; + // Data representation stream includes. + // + for (Context::Streams::ConstIterator i (ctx.istreams.begin ()); + i != ctx.istreams.end (); ++i) + { + if (*i == "CDR") + ctx.os << "#include " << endl + << endl; + else if (*i == "XDR") + ctx.os << "#include " << endl + << endl; + } + + for (Context::Streams::ConstIterator i (ctx.ostreams.begin ()); + i != ctx.ostreams.end (); ++i) + { + if (*i == "CDR") + ctx.os << "#include " << endl + << endl; + else if (*i == "XDR") + ctx.os << "#include " << endl + << endl; + } + if (generate_xml_schema) { Traversal::Schema schema; diff --git a/xsde/cxx/hybrid/tree-header.cxx b/xsde/cxx/hybrid/tree-header.cxx index c7231c9..2412b86 100644 --- a/xsde/cxx/hybrid/tree-header.cxx +++ b/xsde/cxx/hybrid/tree-header.cxx @@ -2379,9 +2379,6 @@ namespace CXX Void generate_tree_header (Context& ctx) { - ctx.os << "#include " << endl - << endl; - Boolean inline_ (ctx.options.value ()); // Emit header includes. diff --git a/xsde/makefile b/xsde/makefile index 953fbdb..a8a4928 100644 --- a/xsde/makefile +++ b/xsde/makefile @@ -60,6 +60,10 @@ cxx_tun += cxx/hybrid/elements.cxx \ cxx/hybrid/tree-inline.cxx \ cxx/hybrid/tree-source.cxx \ cxx/hybrid/tree-type-map.cxx \ + cxx/hybrid/insertion-header.cxx \ + cxx/hybrid/insertion-source.cxx \ + cxx/hybrid/extraction-header.cxx \ + cxx/hybrid/extraction-source.cxx \ cxx/hybrid/parser-name-processor.cxx \ cxx/hybrid/parser-header.cxx \ cxx/hybrid/parser-source.cxx \ -- cgit v1.1