diff options
author | Boris Kolpackov <boris@codesynthesis.com> | 2009-10-27 10:10:46 +0200 |
---|---|---|
committer | Boris Kolpackov <boris@codesynthesis.com> | 2009-10-27 10:10:46 +0200 |
commit | 3dcdc88b14aec626c87f8f480a1d07781a27c069 (patch) | |
tree | 3d64d4701e07441545ffaf3afe0050c4c9e35b41 /xsde/cxx | |
parent | 8161144e7f3182d9dc66a811b4618a81232d4af3 (diff) |
Implement schema enumeration to C++ enum mapping in C++/Hybrid
Diffstat (limited to 'xsde/cxx')
22 files changed, 2118 insertions, 176 deletions
diff --git a/xsde/cxx/hybrid/cli.hxx b/xsde/cxx/hybrid/cli.hxx index 509005a..4e86e41 100644 --- a/xsde/cxx/hybrid/cli.hxx +++ b/xsde/cxx/hybrid/cli.hxx @@ -34,6 +34,7 @@ namespace CXX extern Key suppress_parser_val; extern Key suppress_serializer_val; extern Key omit_default_attributes; + extern Key suppress_enum; extern Key generate_detach; extern Key generate_insertion; extern Key generate_extraction; @@ -122,6 +123,7 @@ namespace CXX suppress_parser_val, Boolean, suppress_serializer_val, Boolean, omit_default_attributes, Boolean, + suppress_enum, Boolean, generate_detach, Boolean, generate_insertion, Cult::Containers::Vector<NarrowString>, generate_extraction, Cult::Containers::Vector<NarrowString>, diff --git a/xsde/cxx/hybrid/default-value.cxx b/xsde/cxx/hybrid/default-value.cxx index e232eae..6abfb05 100644 --- a/xsde/cxx/hybrid/default-value.cxx +++ b/xsde/cxx/hybrid/default-value.cxx @@ -578,6 +578,38 @@ namespace CXX } Void InitValue:: + traverse (SemanticGraph::Enumeration& e) + { + using SemanticGraph::Enumerator; + using SemanticGraph::Enumeration; + + // First see if we should delegate this one to the Complex + // generator. + // + Enumeration* base_enum (0); + + if (!enum_ || !enum_mapping (e, &base_enum)) + { + traverse (static_cast<SemanticGraph::Complex&> (e)); + return; + } + + Enumeration& x (base_enum ? *base_enum : e); + + os << member_ << x.context ().get<String> ("value") << "("; + + Enumeration::NamesIteratorPair ip (x.find (value_)); + + if (ip.first != ip.second) + { + Enumerator& er (dynamic_cast<Enumerator&> (ip.first->named ())); + os << fq_name (e) << "::" << ename (er); + } + + os << ");"; + } + + Void InitValue:: traverse (SemanticGraph::Type& t) { // This is a fall-back case where we handle all other (literal) @@ -1213,6 +1245,21 @@ namespace CXX } Void CompareValue:: + traverse (SemanticGraph::Enumeration& e) + { + // First see if we should delegate this one to the Complex + // generator. + // + if (!enum_ || !enum_mapping (e)) + { + traverse (static_cast<SemanticGraph::Complex&> (e)); + return; + } + + os << *lhs_ << " == " << *rhs_; + } + + Void CompareValue:: traverse (SemanticGraph::Type&) { // This is a fall-back case where we handle all other types. diff --git a/xsde/cxx/hybrid/default-value.hxx b/xsde/cxx/hybrid/default-value.hxx index b9f902c..46a6bf0 100644 --- a/xsde/cxx/hybrid/default-value.hxx +++ b/xsde/cxx/hybrid/default-value.hxx @@ -163,6 +163,7 @@ namespace CXX struct InitValue: Traversal::List, Traversal::Union, Traversal::Complex, + Traversal::Enumeration, Traversal::Type, Traversal::AnySimpleType, @@ -217,6 +218,9 @@ namespace CXX traverse (SemanticGraph::Complex&); virtual Void + traverse (SemanticGraph::Enumeration&); + + virtual Void traverse (SemanticGraph::Type& t); // anySimpleType. @@ -337,6 +341,7 @@ namespace CXX struct CompareValue: Traversal::Union, Traversal::Complex, + Traversal::Enumeration, Traversal::Type, Context { @@ -354,6 +359,9 @@ namespace CXX traverse (SemanticGraph::Complex&); virtual Void + traverse (SemanticGraph::Enumeration&); + + virtual Void traverse (SemanticGraph::Type& t); private: diff --git a/xsde/cxx/hybrid/elements.cxx b/xsde/cxx/hybrid/elements.cxx index 6db57ff..eba0880 100644 --- a/xsde/cxx/hybrid/elements.cxx +++ b/xsde/cxx/hybrid/elements.cxx @@ -39,6 +39,7 @@ namespace CXX detach (ops.value<CLI::generate_detach> ()), mixin (ops.value<CLI::reuse_style_mixin> ()), tiein (!mixin), + enum_ (!ops.value<CLI::suppress_enum> ()), fwd_expr (fe), hxx_expr (he), ixx_expr (ie), @@ -495,6 +496,34 @@ namespace CXX return os; } + Boolean Context:: + enum_mapping (SemanticGraph::Enumeration& e, + SemanticGraph::Enumeration** base) + { + Boolean gen (false); + StringBasedType t (gen); + t.dispatch (e); + + if (gen) + { + // The first enumeration in the inheritance hierarchy breaks + // inheritance. If its base is polymorphic then generating + // the enum mapping will most likely break things. + // + SemanticGraph::Enumeration* b (0); + EnumBasedType t (b); + t.dispatch (e); + + SemanticGraph::Enumeration& first (b ? *b : e); + gen = !polymorphic (first.inherits ().base ()); + + if (gen && base) + *base = b; + } + + return gen; + } + // Namespace // Namespace:: diff --git a/xsde/cxx/hybrid/elements.hxx b/xsde/cxx/hybrid/elements.hxx index 5a94dda..77b91a2 100644 --- a/xsde/cxx/hybrid/elements.hxx +++ b/xsde/cxx/hybrid/elements.hxx @@ -48,6 +48,7 @@ namespace CXX typeinfo (c.typeinfo), mixin (c.mixin), tiein (c.tiein), + enum_ (c.enum_), fwd_expr (c.fwd_expr), hxx_expr (c.hxx_expr), ixx_expr (c.ixx_expr), @@ -78,6 +79,7 @@ namespace CXX typeinfo (c.typeinfo), mixin (c.mixin), tiein (c.tiein), + enum_ (c.enum_), fwd_expr (c.fwd_expr), hxx_expr (c.hxx_expr), ixx_expr (c.ixx_expr), @@ -572,6 +574,13 @@ namespace CXX open_ns (); public: + // Determine whether we are generating the enum mapping for this + // enumeration. Also optionally return the base enum. + // + static Boolean + enum_mapping (SemanticGraph::Enumeration& e, + SemanticGraph::Enumeration** base = 0); + public: typedef Cult::Containers::Deque<String> NamespaceStack; @@ -588,6 +597,7 @@ namespace CXX Boolean typeinfo; Boolean mixin; Boolean tiein; + Boolean enum_; Regex const* fwd_expr; Regex const* hxx_expr; @@ -871,6 +881,124 @@ namespace CXX Boolean& r_; }; + // Check whether this is a string-based type (excluding ID, IDFER, + // anyURI, and ENTITY). + // + struct StringBasedType: Traversal::Complex, + Traversal::Fundamental::String, + Traversal::Fundamental::NormalizedString, + Traversal::Fundamental::Token, + Traversal::Fundamental::Name, + Traversal::Fundamental::NameToken, + Traversal::Fundamental::NCName, + Traversal::Fundamental::Language + { + StringBasedType (Boolean& r) + : r_ (r) + { + *this >> inherits_ >> *this; + } + + virtual Void + traverse (SemanticGraph::Complex& c) + { + inherits (c, inherits_); + } + + // Strings. + // + virtual Void + traverse (SemanticGraph::Fundamental::String&) + { + r_ = true; + } + + virtual Void + traverse (SemanticGraph::Fundamental::NormalizedString&) + { + r_ = true; + } + + virtual Void + traverse (SemanticGraph::Fundamental::Token&) + { + r_ = true; + } + + virtual Void + traverse (SemanticGraph::Fundamental::NameToken&) + { + r_ = true; + } + + virtual Void + traverse (SemanticGraph::Fundamental::Name&) + { + r_ = true; + } + + virtual Void + traverse (SemanticGraph::Fundamental::NCName&) + { + r_ = true; + } + + virtual Void + traverse (SemanticGraph::Fundamental::Language&) + { + r_ = true; + } + + private: + Boolean& r_; + Traversal::Inherits inherits_; + }; + + + // Check whether this is a enumeration-based type. + // + struct EnumBasedType: Traversal::Complex + { + EnumBasedType (SemanticGraph::Enumeration*& e) + : enum_ (e) + { + *this >> inherits_; + + inherits_ >> *this; + inherits_ >> enum_; + } + + virtual Void + traverse (SemanticGraph::Complex& c) + { + inherits (c, inherits_); + } + + private: + struct Enumeration: Traversal::Enumeration + { + Enumeration (SemanticGraph::Enumeration*& e) + : e_ (e) + { + } + + virtual Void + traverse (Type& e) + { + if (e_ == 0) + e_ = &e; + } + + private: + SemanticGraph::Enumeration*& e_; + }; + + + private: + Enumeration enum_; + Traversal::Inherits inherits_; + }; + // // diff --git a/xsde/cxx/hybrid/extraction-header.cxx b/xsde/cxx/hybrid/extraction-header.cxx index dc729f6..e2ed714 100644 --- a/xsde/cxx/hybrid/extraction-header.cxx +++ b/xsde/cxx/hybrid/extraction-header.cxx @@ -14,6 +14,47 @@ namespace CXX { namespace { + struct Enumeration : Traversal::Enumeration, Context + { + Enumeration (Context& c, Traversal::Complex& complex) + : Context (c), complex_ (complex) + { + } + + virtual Void + traverse (Type& e) + { + // First see if we should delegate this one to the Complex + // generator. + // + if (!enum_ || !enum_mapping (e)) + { + complex_.traverse (e); + return; + } + + String const& name (ename_custom (e)); + + // We may not need to generate the class if this type is + // being customized. + // + if (!name) + return; + + for (Streams::ConstIterator i (istreams.begin ()); + i != istreams.end (); ++i) + { + os << (exceptions ? "void" : "bool") << endl + << "operator>> (" << istream (*i) << "&," << endl + << name << "&);" + << endl; + } + } + + private: + Traversal::Complex& complex_; + }; + struct List : Traversal::List, Context { List (Context& c) @@ -256,6 +297,7 @@ namespace CXX List list (ctx); Union union_ (ctx); Complex complex (ctx); + Enumeration enumeration (ctx, complex); schema >> sources >> schema; schema >> names_ns >> ns >> names; @@ -263,6 +305,7 @@ namespace CXX names >> list; names >> union_; names >> complex; + names >> enumeration; schema.dispatch (ctx.schema_root); } diff --git a/xsde/cxx/hybrid/extraction-source.cxx b/xsde/cxx/hybrid/extraction-source.cxx index 5460740..e829760 100644 --- a/xsde/cxx/hybrid/extraction-source.cxx +++ b/xsde/cxx/hybrid/extraction-source.cxx @@ -14,6 +14,60 @@ namespace CXX { namespace { + struct Enumeration : Traversal::Enumeration, Context + { + Enumeration (Context& c, Traversal::Complex& complex) + : Context (c), complex_ (complex) + { + } + + virtual Void + traverse (Type& e) + { + // First see if we should delegate this one to the Complex + // generator. + // + if (!enum_ || !enum_mapping (e)) + { + complex_.traverse (e); + return; + } + + String const& name (ename_custom (e)); + + // We may not need to generate the class if this type is + // being customized. + // + if (!name) + return; + + for (Streams::ConstIterator i (istreams.begin ()); + i != istreams.end (); ++i) + { + os << (exceptions ? "void" : "bool") << endl + << "operator>> (" << istream (*i) << "& s," << endl + << name << "& x)" + << "{" + << "unsigned int i;"; + + if (exceptions) + os << "s >> i;"; + else + os << "if (!(s >> i))" << endl + << "return false;"; + + os << "x = static_cast< " << name << "::" << + e.context ().get<String> ("value-type") << " > (i);" + << (exceptions ? "" : "return true;") + << "}" + << endl; + } + } + + private: + Traversal::Complex& complex_; + }; + struct List : Traversal::List, Context { List (Context& c) @@ -1102,6 +1156,7 @@ namespace CXX List list (ctx); Union union_ (ctx); Complex complex (ctx); + Enumeration enumeration (ctx, complex); schema >> sources >> schema; schema >> names_ns >> ns >> names; @@ -1109,6 +1164,7 @@ namespace CXX names >> list; names >> union_; names >> complex; + names >> enumeration; schema.dispatch (ctx.schema_root); } diff --git a/xsde/cxx/hybrid/generator.cxx b/xsde/cxx/hybrid/generator.cxx index 78b9142..c7dcb1d 100644 --- a/xsde/cxx/hybrid/generator.cxx +++ b/xsde/cxx/hybrid/generator.cxx @@ -122,6 +122,7 @@ namespace CXX extern Key suppress_parser_val = "suppress-parser-val"; extern Key suppress_serializer_val = "suppress-serializer-val"; extern Key omit_default_attributes = "omit-default-attributes"; + extern Key suppress_enum = "suppress-enum"; extern Key generate_detach = "generate-detach"; extern Key generate_insertion = "generate-insertion"; extern Key generate_extraction = "generate-extraction"; @@ -257,6 +258,11 @@ namespace CXX << " from serialized XML documents." << endl; + e << "--suppress-enum" << endl + << " Suppress the generation of the XML Schema\n" + << " enumeration to C++ enum mapping." + << endl; + e << "--generate-detach" << endl << " Generate detach functions for elements and\n" << " attributes of variable-length types." diff --git a/xsde/cxx/hybrid/insertion-header.cxx b/xsde/cxx/hybrid/insertion-header.cxx index 4898c02..b1a4dbe 100644 --- a/xsde/cxx/hybrid/insertion-header.cxx +++ b/xsde/cxx/hybrid/insertion-header.cxx @@ -14,6 +14,47 @@ namespace CXX { namespace { + struct Enumeration : Traversal::Enumeration, Context + { + Enumeration (Context& c, Traversal::Complex& complex) + : Context (c), complex_ (complex) + { + } + + virtual Void + traverse (Type& e) + { + // First see if we should delegate this one to the Complex + // generator. + // + if (!enum_ || !enum_mapping (e)) + { + complex_.traverse (e); + return; + } + + String const& name (ename_custom (e)); + + // We may not need to generate the class if this type is + // being customized. + // + if (!name) + return; + + for (Streams::ConstIterator i (ostreams.begin ()); + i != ostreams.end (); ++i) + { + os << (exceptions ? "void" : "bool") << endl + << "operator<< (" << ostream (*i) << "&," << endl + << "const " << name << "&);" + << endl; + } + } + + private: + Traversal::Complex& complex_; + }; + struct List : Traversal::List, Context { List (Context& c) @@ -256,6 +297,7 @@ namespace CXX List list (ctx); Union union_ (ctx); Complex complex (ctx); + Enumeration enumeration (ctx, complex); schema >> sources >> schema; schema >> names_ns >> ns >> names; @@ -263,6 +305,7 @@ namespace CXX names >> list; names >> union_; names >> complex; + names >> enumeration; schema.dispatch (ctx.schema_root); } diff --git a/xsde/cxx/hybrid/insertion-source.cxx b/xsde/cxx/hybrid/insertion-source.cxx index 7dc6fcb..7fce9ee 100644 --- a/xsde/cxx/hybrid/insertion-source.cxx +++ b/xsde/cxx/hybrid/insertion-source.cxx @@ -14,6 +14,51 @@ namespace CXX { namespace { + struct Enumeration : Traversal::Enumeration, Context + { + Enumeration (Context& c, Traversal::Complex& complex) + : Context (c), complex_ (complex) + { + } + + virtual Void + traverse (Type& e) + { + // First see if we should delegate this one to the Complex + // generator. + // + if (!enum_ || !enum_mapping (e)) + { + complex_.traverse (e); + return; + } + + String const& name (ename_custom (e)); + + // We may not need to generate the class if this type is + // being customized. + // + if (!name) + return; + + for (Streams::ConstIterator i (ostreams.begin ()); + i != ostreams.end (); ++i) + { + os << (exceptions ? "void" : "bool") << endl + << "operator<< (" << ostream (*i) << "& s," << endl + << "const " << name << "& x)" + << "{" + << "unsigned int i = x;" + << (exceptions ? "" : "return ") << "s << i;" + << "}" + << endl; + } + } + + private: + Traversal::Complex& complex_; + }; + struct List : Traversal::List, Context { List (Context& c) @@ -721,6 +766,7 @@ namespace CXX List list (ctx); Union union_ (ctx); Complex complex (ctx); + Enumeration enumeration (ctx, complex); schema >> sources >> schema; schema >> names_ns >> ns >> names; @@ -728,6 +774,7 @@ namespace CXX names >> list; names >> union_; names >> complex; + names >> enumeration; schema.dispatch (ctx.schema_root); } diff --git a/xsde/cxx/hybrid/parser-header.cxx b/xsde/cxx/hybrid/parser-header.cxx index c174df4..d8948d7 100644 --- a/xsde/cxx/hybrid/parser-header.cxx +++ b/xsde/cxx/hybrid/parser-header.cxx @@ -14,6 +14,194 @@ namespace CXX { namespace { + // + // + struct PostOverride: Traversal::Complex, Context + { + PostOverride (Context& c) + : Context (c) + { + } + + virtual Void + traverse (SemanticGraph::Complex& c) + { + if (c.inherits_p ()) + { + SemanticGraph::Type& b (c.inherits ().base ()); + + if (polymorphic (b)) + { + if (tiein) + dispatch (b); + + os << "virtual " << pret_type (b) << endl + << post_name (b) << " ();" + << endl; + } + } + } + }; + + // + // + struct Enumeration: Traversal::Enumeration, Context + { + Enumeration (Context& c, Traversal::Complex& complex) + : Context (c), complex_ (complex), post_override_ (c) + { + } + + virtual Void + traverse (Type& e) + { + // First see if we should delegate this one to the Complex + // generator. + // + Type* base_enum (0); + + if (!enum_ || !enum_mapping (e, &base_enum)) + { + complex_.traverse (e); + return; + } + + String const& name (epimpl_custom (e)); + + // We may not need to generate the class if this parser is + // being customized. + // + if (name) + { + Boolean fl (fixed_length (e)); + SemanticGraph::Type& b (e.inherits ().base ()); + + os << "class " << name << ": public " << + (mixin ? "virtual " : "") << epskel (e); + + // Derive from base pimpl even if base_enum == 0. This is done + // so that we have implementations for all the (otherwise pure + // virtual) post_*() functions. + // + if (mixin) + os << "," << endl + << " public " << fq_name (b, "p:impl"); + + os << "{" + << "public:" << endl; + + // c-tor + // + if (!fl || tiein) + os << name << " (" << (fl ? "" : "bool = false") << ");" + << endl; + + if (!fl) + { + // d-tor + // + os << "~" << name << " ();" + << endl; + + // reset + // + if (reset) + os << "virtual void" << endl + << "_reset ();" + << endl; + } + + // pre + // + os << "virtual void" << endl + << "pre ();" + << endl; + + // _characters + // + if (!base_enum) + os << "virtual void" << endl + << "_characters (const " << string_type << "&);" + << endl; + + // post + // + String const& ret (pret_type (e)); + + if (polymorphic (e)) + post_override_.dispatch (e); + + os << "virtual " << ret << endl + << post_name (e) << " ();" + << endl; + + String const& type (fq_name (e)); + + // pre_impl + // + if (!fl) + os << (tiein ? "public:" : "protected:") << endl + << "void" << endl + << pre_impl_name (e) << " (" << type << "*);" + << endl; + + // Base implementation. + // + if (tiein && base_enum) + os << (tiein ? "public:" : "protected:") << endl + << fq_name (b, "p:impl") << " base_impl_;" + << endl; + + // State. + // + if (!fl || !base_enum) + { + String const& state_type (epstate_type (e)); + + os << (tiein ? "public:" : "protected:") << endl + << "struct " << state_type + << "{"; + + if (!fl) + os << type << "* " << "x_;"; + + if (!base_enum) + { + if (stl) + os << "::std::string str_;"; + else + os << "::xsde::cxx::string str_;"; + } + + os << "};" + << state_type << " " << epstate (e) << ";"; + } + + if (!fl) + os << "bool " << epstate_base (e) << ";"; + + os << "};"; + } + + // Generate include for custom parser. + // + if (e.context ().count ("p:impl-include")) + { + close_ns (); + + os << "#include " << process_include_path ( + e.context ().get<String> ("p:impl-include")) << endl + << endl; + + open_ns (); + } + } + + private: + Traversal::Complex& complex_; + PostOverride post_override_; + }; + struct List: Traversal::List, Context { List (Context& c) @@ -352,35 +540,6 @@ namespace CXX // // - struct PostOverride: Traversal::Complex, Context - { - PostOverride (Context& c) - : Context (c) - { - } - - virtual Void - traverse (SemanticGraph::Complex& c) - { - if (c.inherits_p ()) - { - SemanticGraph::Type& b (c.inherits ().base ()); - - if (polymorphic (b)) - { - if (tiein) - dispatch (b); - - os << "virtual " << pret_type (b) << endl - << post_name (b) << " ();" - << endl; - } - } - } - }; - - // - // struct Complex : Traversal::Complex, Context { Complex (Context& c) @@ -624,10 +783,12 @@ namespace CXX List list (ctx); Union union_ (ctx); Complex complex (ctx); + Enumeration enumeration (ctx, complex); names >> list; names >> union_; names >> complex; + names >> enumeration; schema.dispatch (ctx.schema_root); } diff --git a/xsde/cxx/hybrid/parser-name-processor.cxx b/xsde/cxx/hybrid/parser-name-processor.cxx index c635aec..819280f 100644 --- a/xsde/cxx/hybrid/parser-name-processor.cxx +++ b/xsde/cxx/hybrid/parser-name-processor.cxx @@ -4,6 +4,7 @@ // license : GNU GPL v2 + exceptions; see accompanying LICENSE file #include <cxx/elements.hxx> +#include <cxx/hybrid/elements.hxx> #include <cxx/hybrid/parser-name-processor.hxx> #include <xsd-frontend/semantic-graph.hxx> @@ -251,6 +252,61 @@ namespace CXX // // + struct Enumeration: Traversal::Enumeration, Context + { + Enumeration (Context& c, Traversal::Complex& complex) + : Context (c), complex_ (complex) + { + } + + virtual Void + traverse (Type& e) + { + // First see if we should delegate this one to the Complex + // generator. + // + Type* base_enum (0); + + if (options.value<CLI::suppress_enum> () || + !Hybrid::Context::enum_mapping (e, &base_enum)) + { + complex_.traverse (e); + return; + } + + SemanticGraph::Context& ec (e.context ()); + + // In case of customization use p:impl-base instead of p:impl. + // If the name is empty then we are not generating anything. + // + String const& name (ec.count ("p:impl-base") + ? ec.get<String> ("p:impl-base") + : ec.get<String> ("p:impl")); + if (!name) + return; + + Boolean fl (fixed_length (e)); + + NameSet set; + set.insert (name); + + if (!fl || !base_enum) + { + String state_type (find_name (name + L"_state", set)); + ec.set ("pstate-type", state_type); + ec.set ("pstate", find_name (state_type, "_", set)); + } + + if (!fl) + ec.set ("pstate-base", find_name (name + L"_base", "_", set)); + } + + private: + Traversal::Complex& complex_; + }; + + // + // struct List: Traversal::List, Context { List (Context& c) @@ -708,10 +764,12 @@ namespace CXX List list (ctx); Union union_ (ctx); Complex complex (ctx); + Enumeration enumeration (ctx, complex); ns_names >> list; ns_names >> union_; ns_names >> complex; + ns_names >> enumeration; schema.dispatch (tu); } diff --git a/xsde/cxx/hybrid/parser-source.cxx b/xsde/cxx/hybrid/parser-source.cxx index c877e1d..e5bbb90 100644 --- a/xsde/cxx/hybrid/parser-source.cxx +++ b/xsde/cxx/hybrid/parser-source.cxx @@ -14,6 +14,423 @@ namespace CXX { namespace { + // + // + struct PostOverride: Traversal::Complex, Context + { + PostOverride (Context& c) + : Context (c), scope_ (0) + { + } + + virtual Void + traverse (SemanticGraph::Complex& c) + { + Boolean clear (false); + + if (scope_ == 0) + { + scope_ = &c; + clear = true; + } + + if (c.inherits_p ()) + { + SemanticGraph::Type& b (c.inherits ().base ()); + + if (polymorphic (b)) + { + if (tiein) + dispatch (b); + + String const& scope (epimpl_custom (*scope_)); + + os << pret_type (b) << " " << scope << "::" << endl + << post_name (b) << " ()" + << "{" + << "return this->" << post_name (c) << " ();" + << "}"; + } + } + + if (clear) + scope_ = 0; + } + + private: + SemanticGraph::Complex* scope_; + }; + + // + // + struct Enumerator: Traversal::Enumerator, Context + { + Enumerator (Context& c) + : Context (c) + { + } + + virtual Void + traverse (Type& e) + { + using SemanticGraph::Enumeration; + + Enumeration& s (dynamic_cast<Enumeration&> (e.scope ())); + + os << "if (strcmp (s, " << + strlit (e.name ()) << ") == 0)" << endl + << "v = " << fq_name (s) << "::" << ename (e) << ";"; + } + }; + + // + // + struct Enumeration: Traversal::Enumeration, Context + { + Enumeration (Context& c, Traversal::Complex& complex) + : Context (c), + complex_ (complex), + post_override_ (c), + enumerator_ (c) + { + names_ >> enumerator_; + } + + virtual Void + traverse (Type& e) + { + // First see if we should delegate this one to the Complex + // generator. + // + Type* base_enum (0); + + if (!enum_ || !enum_mapping (e, &base_enum)) + { + complex_.traverse (e); + return; + } + + String const& name (epimpl_custom (e)); + + if (!name) + return; + + os << "// " << name << endl + << "//" << endl + << endl; + + Boolean fl (fixed_length (e)); + + SemanticGraph::Context& ec (e.context ()); + SemanticGraph::Type& b (e.inherits ().base ()); + + String const& type (fq_name (e)); + String state; + + if (!fl || !base_enum) + state = epstate (e); + + // c-tor + // + if (!fl || tiein) + { + os << name << "::" << endl + << name << " (" << (fl ? "" : "bool b") << ")"; + + if (tiein) + os << endl + << ": " << epskel (e) << " (" << + (base_enum ? "&base_impl_" : "0") << ")"; + + if (base_enum && !fixed_length (b)) + { + if (tiein) + os << "," << endl + << " base_impl_" << " (true)"; + else + os << endl + << ": " << fq_name (b, "p:impl") << " (true)"; + } + + os << "{"; + + if (!fl) + { + os << "this->" << epstate_base (e) << " = b;" + << "this->" << state << ".x_ = 0;"; + } + + os << "}"; + } + + if (!fl) + { + // d-tor + // + os << name << "::" << endl + << "~" << name << " ()" + << "{" + << "if (!this->" << epstate_base (e) << ")" << endl + << "delete this->" << state << ".x_;" + << "}"; + + // reset + // + if (reset) + { + os << "void " << name << "::" << endl + << "_reset ()" + << "{"; + + if (mixin && base_enum) + os << epimpl (b) << "::_reset ();"; + + os << epskel (e) << "::_reset ();" + << endl; + + os << "if (!this->" << epstate_base (e) << ")" + << "{" + << "delete this->" << state << ".x_;" + << "this->" << state << ".x_ = 0;" + << "}" + << "}"; + } + } + + // pre_impl + // + if (!fl) + { + os << "void " << name << "::" << endl + << pre_impl_name (e) << " (" << type << "* x)" + << "{" + << "this->" << state << ".x_ = x;"; + + // Call base pre_impl (var-length) or pre (fix-length). + // + if (base_enum) + { + if (tiein) + os << "this->base_impl_."; + else + os << epimpl (b) << "::"; //@@ fq-name. + + if (fixed_length (b)) + os << "pre ();"; + else + os << pre_impl_name (b) << " (x);"; + } + + // Clear the string buffer. + // + if (!base_enum) + { + if (stl) + os << "this->" << state << ".str_.clear ();"; + else + { + if (exceptions) + os << "this->" << state << ".str_.assign (\"\", 0);"; + else + { + os << endl + << "if (this->" << state << ".str_.assign (\"\", 0))" << endl + << "this->_sys_error (::xsde::cxx::sys_error::no_memory);"; + } + } + } + + os << "}"; + } + + // pre + // + os << "void " << name << "::" << endl + << "pre ()" + << "{"; + + if (fl) + { + if (base_enum) + { + // Our base is also fixed-length so call its pre() + // + if (tiein) + os << "this->base_impl_."; + else + os << epimpl (b) << "::"; //@@ fq-name. + + os << "pre ();"; + } + + // Clear the string buffer. + // + if (!base_enum) + { + if (stl) + os << "this->" << state << ".str_.clear ();"; + else + { + if (exceptions) + os << "this->" << state << ".str_.assign (\"\", 0);"; + else + { + os << endl + << "if (this->" << state << ".str_.assign (\"\", 0))" << endl + << "this->_sys_error (::xsde::cxx::sys_error::no_memory);"; + } + } + } + } + else + { + if (exceptions) + os << "this->" << pre_impl_name (e) << " (new " << type << ");"; + else + os << type << "* x = new " << type << ";" + << "if (x)" << endl + << "this->" << pre_impl_name (e) << " (x);" + << "else" << endl + << "this->_sys_error (::xsde::cxx::sys_error::no_memory);"; + } + + os << "}"; + + // _characters + // + if (!base_enum) + { + os << "void " << name << "::" << endl + << "_characters (const " << string_type << "& s)" + << "{"; + + if (stl) + os << "this->" << state << ".str_.append (s.data (), s.size ());"; + else + { + if (exceptions) + os << "this->" << state << ".str_.append (s.data (), s.size ());"; + else + { + os << "if (this->" << state << ".str_.append (" << + "s.data (), s.size ()))" << endl + << "this->_sys_error (::xsde::cxx::sys_error::no_memory);"; + } + } + + os << "}"; + } + + // post + // + String const& ret (pret_type (e)); + + if (polymorphic (e)) + post_override_.dispatch (e); + + os << ret << " " << name << "::" << endl + << post_name (e) << " ()" + << "{"; + + if (base_enum) + { + if (fl) + { + os << type << " r;" + << "static_cast< " << fq_name (b) << "& > (r) = "; + + if (tiein) + os << "this->base_impl_."; + else + os << epimpl (b) << "::"; //@@ fq-name. + + os << post_name (b) << " ();"; + } + else + { + os << type << "* r = this->" << state << ".x_;" + << "this->" << state << ".x_ = 0;"; + + Boolean flb (fixed_length (b)); + + // Copy the value if our base is fixed-length. + // + if (flb) + os << "r->" << base_enum->context ().get<String> ("value") << + " ("; + + if (tiein) + os << "this->base_impl_."; + else + os << epimpl (b) << "::"; //@@ fq-name. + + os << post_name (b) << " ()"; + + if (flb) + os << ")"; + + os << ";"; + } + + // + // @@ TODO: check enumerators (switch) + // + } + else + { + String const& vt (ec.get<String> ("value-type")); + + os << type << "::" << vt << " v = static_cast< " << type << + "::" << vt << " > (0);" + << "const char* s = this->" << state << ".str_." << + (stl ? "c_str" : "data") << " ();" + << endl; + + names<Enumeration> (e, names_, 0, 0, 0, &Enumeration::comma); + + + /* + // @@ Cannot do error checking in post. + + if (!options.value<CLI::suppress_validation> () && + !options.value<CLI::suppress_parser_val> ()) + { + os << "else" << endl + << "this->_schema_error (" << + "::xsde::cxx::schema_error::invalid_enumeration_value);"; + } + */ + + os << endl; + + if (fl) + os << type << " r (v);"; + else + os << type << "* r = this->" << state << ".x_;" + << "this->" << state << ".x_ = 0;" + << "r->" << ec.get<String> ("value") << " (v);"; + } + + os << "return r;" + << "}"; + } + + virtual Void + comma (Type&) + { + os << "else "; + } + + private: + Traversal::Complex& complex_; + PostOverride post_override_; + + Traversal::Names names_; + Enumerator enumerator_; + }; + + // + // struct List: Traversal::List, Context { List (Context& c) @@ -907,53 +1324,6 @@ namespace CXX // // - struct PostOverride: Traversal::Complex, Context - { - PostOverride (Context& c) - : Context (c), scope_ (0) - { - } - - virtual Void - traverse (SemanticGraph::Complex& c) - { - Boolean clear (false); - - if (scope_ == 0) - { - scope_ = &c; - clear = true; - } - - if (c.inherits_p ()) - { - SemanticGraph::Type& b (c.inherits ().base ()); - - if (polymorphic (b)) - { - if (tiein) - dispatch (b); - - String const& scope (epimpl_custom (*scope_)); - - os << pret_type (b) << " " << scope << "::" << endl - << post_name (b) << " ()" - << "{" - << "return this->" << post_name (c) << " ();" - << "}"; - } - } - - if (clear) - scope_ = 0; - } - - private: - SemanticGraph::Complex* scope_; - }; - - // - // struct Complex: Traversal::Complex, Context { Complex (Context& c) @@ -1444,10 +1814,12 @@ namespace CXX List list (ctx); Union union_ (ctx); Complex complex (ctx); + Enumeration enumeration (ctx, complex); names >> list; names >> union_; names >> complex; + names >> enumeration; schema.dispatch (ctx.schema_root); } diff --git a/xsde/cxx/hybrid/serializer-header.cxx b/xsde/cxx/hybrid/serializer-header.cxx index 153da8d..b36b910 100644 --- a/xsde/cxx/hybrid/serializer-header.cxx +++ b/xsde/cxx/hybrid/serializer-header.cxx @@ -14,6 +14,141 @@ namespace CXX { namespace { + // + // + struct PreOverride: Traversal::Complex, Context + { + PreOverride (Context& c) + : Context (c) + { + } + + virtual Void + traverse (SemanticGraph::Complex& c) + { + if (c.inherits_p ()) + { + SemanticGraph::Type& b (c.inherits ().base ()); + + if (polymorphic (b)) + { + if (tiein) + dispatch (b); + + os << "virtual void" << endl + << "pre (" << sarg_type (b) << ");" + << endl; + } + } + } + }; + + // + // + struct Enumeration: Traversal::Enumeration, Context + { + Enumeration (Context& c, Traversal::Complex& complex) + : Context (c), complex_ (complex), pre_override_ (c) + { + } + + virtual Void + traverse (Type& e) + { + // First see if we should delegate this one to the Complex + // generator. + // + Type* base_enum (0); + + if (!enum_ || !enum_mapping (e, &base_enum)) + { + complex_.traverse (e); + return; + } + + String const& name (esimpl_custom (e)); + + // We may not need to generate the class if this serializer is + // being customized. + // + if (name) + { + String const& arg (sarg_type (e)); + SemanticGraph::Type& b (e.inherits ().base ()); + + os << "class " << name << ": public " << + (mixin ? "virtual " : "") << esskel (e); + + // Derive from base simpl even if base_enum == 0. This is done + // so that we have implementations for all the (otherwise pure + // virtual) pre() functions. + // + if (mixin) + os << "," << endl + << " public " << fq_name (b, "s:impl"); + + os << "{" + << "public:" << endl; + + // c-tor + // + if (tiein) + os << name << " ();" + << endl; + + // pre + // + if (polymorphic (e)) + pre_override_.dispatch (e); + + os << "virtual void" << endl + << "pre (" << arg << ");" + << endl; + + // _serialize_content + // + if (!base_enum) + os << "virtual void" << endl + << "_serialize_content ();" + << endl; + + // State. + // + if (!base_enum) + { + os << (tiein ? "public:" : "protected:") << endl + << "const " << fq_name (e) << "* " << esstate (e) << ";"; + } + else if (tiein) + { + os << "public:" << endl + << fq_name (b, "s:impl") << " base_impl_;"; + } + + os << "};"; + } + + // Generate include for custom serializer. + // + if (e.context ().count ("s:impl-include")) + { + close_ns (); + + os << "#include " << process_include_path ( + e.context ().get<String> ("s:impl-include")) << endl + << endl; + + open_ns (); + } + } + + private: + Traversal::Complex& complex_; + PreOverride pre_override_; + }; + + // + // struct List: Traversal::List, Context { List (Context& c) @@ -343,35 +478,6 @@ namespace CXX // // - struct PreOverride: Traversal::Complex, Context - { - PreOverride (Context& c) - : Context (c) - { - } - - virtual Void - traverse (SemanticGraph::Complex& c) - { - if (c.inherits_p ()) - { - SemanticGraph::Type& b (c.inherits ().base ()); - - if (polymorphic (b)) - { - if (tiein) - dispatch (b); - - os << "virtual void" << endl - << "pre (" << sarg_type (b) << ");" - << endl; - } - } - } - }; - - // - // struct Complex : Traversal::Complex, Context { Complex (Context& c) @@ -511,7 +617,7 @@ namespace CXX if (tiein && hb) - os << (tiein ? "public:" : "protected:") << endl + os << "public:" << endl << fq_name (c.inherits ().base (), "s:impl") << " base_impl_;" << endl; @@ -605,10 +711,12 @@ namespace CXX List list (ctx); Union union_ (ctx); Complex complex (ctx); + Enumeration enumeration (ctx, complex); names >> list; names >> union_; names >> complex; + names >> enumeration; schema.dispatch (ctx.schema_root); } diff --git a/xsde/cxx/hybrid/serializer-name-processor.cxx b/xsde/cxx/hybrid/serializer-name-processor.cxx index 2f7d296..159e3b0 100644 --- a/xsde/cxx/hybrid/serializer-name-processor.cxx +++ b/xsde/cxx/hybrid/serializer-name-processor.cxx @@ -4,6 +4,7 @@ // license : GNU GPL v2 + exceptions; see accompanying LICENSE file #include <cxx/elements.hxx> +#include <cxx/hybrid/elements.hxx> #include <cxx/hybrid/serializer-name-processor.hxx> #include <xsd-frontend/semantic-graph.hxx> @@ -244,6 +245,54 @@ namespace CXX // // + struct Enumeration: Traversal::Enumeration, Context + { + Enumeration (Context& c, Traversal::Complex& complex) + : Context (c), complex_ (complex) + { + } + + virtual Void + traverse (Type& e) + { + // First see if we should delegate this one to the Complex + // generator. + // + Type* base_enum (0); + + if (options.value<CLI::suppress_enum> () || + !Hybrid::Context::enum_mapping (e, &base_enum)) + { + complex_.traverse (e); + return; + } + + SemanticGraph::Context& ec (e.context ()); + + // In case of customization use s:impl-base instead of s:impl. + // If the name is empty then we are not generating anything. + // + String const& name (ec.count ("s:impl-base") + ? ec.get<String> ("s:impl-base") + : ec.get<String> ("s:impl")); + if (!name) + return; + + if (!base_enum) + { + NameSet set; + set.insert (name); + + ec.set ("sstate", find_name (name + L"_state", "_", set)); + } + } + + private: + Traversal::Complex& complex_; + }; + + // + // struct List: Traversal::List, Context { List (Context& c) @@ -288,9 +337,9 @@ namespace CXX } virtual Void - traverse (Type& l) + traverse (Type& u) { - SemanticGraph::Context& uc (l.context ()); + SemanticGraph::Context& uc (u.context ()); // In case of customization use s:impl-base instead of s:impl. // If the name is empty then we are not generating anything. @@ -723,10 +772,12 @@ namespace CXX List list (ctx); Union union_ (ctx); Complex complex (ctx); + Enumeration enumeration (ctx, complex); ns_names >> list; ns_names >> union_; ns_names >> complex; + ns_names >> enumeration; schema.dispatch (tu); } diff --git a/xsde/cxx/hybrid/serializer-source.cxx b/xsde/cxx/hybrid/serializer-source.cxx index 0aeaf89..1268631 100644 --- a/xsde/cxx/hybrid/serializer-source.cxx +++ b/xsde/cxx/hybrid/serializer-source.cxx @@ -70,6 +70,155 @@ namespace CXX // // + struct PreOverride: Traversal::Complex, Context + { + PreOverride (Context& c) + : Context (c), scope_ (0) + { + } + + virtual Void + traverse (SemanticGraph::Complex& c) + { + Boolean clear (false); + + if (scope_ == 0) + { + scope_ = &c; + clear = true; + } + + if (c.inherits_p ()) + { + SemanticGraph::Type& b (c.inherits ().base ()); + + if (polymorphic (b)) + { + if (tiein) + dispatch (b); + + String const& scope (esimpl_custom (*scope_)); + + os << "void " << scope << "::" << endl + << "pre (" << sarg_type (b) << " x)" + << "{" + << "this->pre (static_cast< " << sarg_type (c) << " > (x));" + << "}"; + } + } + + if (clear) + scope_ = 0; + } + + private: + SemanticGraph::Complex* scope_; + }; + + // + // + struct Enumeration: Traversal::Enumeration, Context + { + Enumeration (Context& c, Traversal::Complex& complex) + : Context (c), + complex_ (complex), + pre_override_ (c), + type_pass_(c) + { + } + + virtual Void + traverse (Type& e) + { + // First see if we should delegate this one to the Complex + // generator. + // + Type* base_enum (0); + + if (!enum_ || !enum_mapping (e, &base_enum)) + { + complex_.traverse (e); + return; + } + + String const& name (esimpl_custom (e)); + + if (!name) + return; + + String state; + + if (!base_enum) + state = esstate (e); + + os << "// " << name << endl + << "//" << endl + << endl; + + // c-tor + // + if (tiein) + { + os << name << "::" << endl + << name << " ()" << endl + << ": " << esskel (e) << " (" << + (base_enum ? "&base_impl_" : "0") << ")" + << "{" + << "}"; + } + + // pre + // + String const& arg (sarg_type (e)); + + if (polymorphic (e)) + pre_override_.dispatch (e); + + os << "void " << name << "::" << endl + << "pre (" << arg << " x)" + << "{"; + + if (base_enum) + { + SemanticGraph::Type& b (e.inherits ().base ()); + + if (tiein) + os << "this->base_impl_.pre ("; + else + os << esimpl (b) << "::pre ("; + + type_pass_.dispatch (b); + + os << "x);"; + } + else + os << "this->" << state << " = &x;"; + + os << "}"; + + // _serialize_content + // + if (!base_enum) + { + String const& string (e.context ().get<String> ("string")); + + os << "void " << name << "::" << endl + << "_serialize_content ()" + << "{" + << "this->_characters (this->" << state << "->" << + string << " ());" + << "}"; + } + } + + private: + Traversal::Complex& complex_; + PreOverride pre_override_; + TypePass type_pass_; + }; + + // + // struct List: Traversal::List, Context { List (Context& c) @@ -931,53 +1080,6 @@ namespace CXX // // - struct PreOverride: Traversal::Complex, Context - { - PreOverride (Context& c) - : Context (c), scope_ (0) - { - } - - virtual Void - traverse (SemanticGraph::Complex& c) - { - Boolean clear (false); - - if (scope_ == 0) - { - scope_ = &c; - clear = true; - } - - if (c.inherits_p ()) - { - SemanticGraph::Type& b (c.inherits ().base ()); - - if (polymorphic (b)) - { - if (tiein) - dispatch (b); - - String const& scope (esimpl_custom (*scope_)); - - os << "void " << scope << "::" << endl - << "pre (" << sarg_type (b) << " x)" - << "{" - << "this->pre (static_cast< " << sarg_type (c) << " > (x));" - << "}"; - } - } - - if (clear) - scope_ = 0; - } - - private: - SemanticGraph::Complex* scope_; - }; - - // - // struct Complex: Traversal::Complex, Context { Complex (Context& c) @@ -1125,7 +1227,6 @@ namespace CXX if (!b.is_a<SemanticGraph::AnyType> () && !b.is_a<SemanticGraph::AnySimpleType> ()) { - if (tiein) os << "this->base_impl_.pre ("; else @@ -1290,10 +1391,12 @@ namespace CXX List list (ctx); Union union_ (ctx); Complex complex (ctx); + Enumeration enumeration (ctx, complex); names >> list; names >> union_; names >> complex; + names >> enumeration; schema.dispatch (ctx.schema_root); } diff --git a/xsde/cxx/hybrid/tree-forward.cxx b/xsde/cxx/hybrid/tree-forward.cxx index 17a4916..bd53f9d 100644 --- a/xsde/cxx/hybrid/tree-forward.cxx +++ b/xsde/cxx/hybrid/tree-forward.cxx @@ -14,6 +14,50 @@ namespace CXX { namespace { + struct Enumeration : Traversal::Enumeration, Context + { + Enumeration (Context& c, Traversal::Complex& complex) + : Context (c), complex_ (complex) + { + } + + virtual Void + traverse (Type& e) + { + // First see if we should delegate this one to the Complex + // generator. + // + if (!enum_ || !enum_mapping (e)) + { + complex_.traverse (e); + return; + } + + SemanticGraph::Context& ctx (e.context ()); + + // Forward-declare the base. + // + if (ctx.count ("name-base")) + { + if (String base = ctx.get<String> ("name-base")) + os << "class " << base << ";"; + } + + // Typedef or forward-declare the type. + // + if (ctx.count ("name-typedef")) + { + os << "typedef " << ctx.get<String> ("name-typedef") << " " << + ename (e) << ";"; + } + else + os << "class " << ename (e) << ";"; + } + + private: + Traversal::Complex& complex_; + }; + struct List : Traversal::List, Context { List (Context& c) @@ -752,7 +796,7 @@ namespace CXX List list (ctx); Union union_ (ctx); Complex complex (ctx); - //Enumeration enumeration (ctx); + Enumeration enumeration (ctx, complex); schema >> sources >> schema; schema >> names_ns >> ns >> names; @@ -760,7 +804,7 @@ namespace CXX names >> list; names >> union_; names >> complex; - //names >> enumeration; + names >> enumeration; schema.dispatch (ctx.schema_root); diff --git a/xsde/cxx/hybrid/tree-header.cxx b/xsde/cxx/hybrid/tree-header.cxx index 929ea6e..aba65c7 100644 --- a/xsde/cxx/hybrid/tree-header.cxx +++ b/xsde/cxx/hybrid/tree-header.cxx @@ -14,6 +14,229 @@ namespace CXX { namespace { + struct Enumerator: Traversal::Enumerator, Context + { + Enumerator (Context& c) + : Context (c) + { + } + + virtual Void + traverse (Type& e) + { + os << ename (e); + } + }; + + struct Enumeration : Traversal::Enumeration, Context + { + Enumeration (Context& c, Traversal::Complex& complex) + : Context (c), + complex_ (complex), + base_name_ (c, TypeName::base), + enumerator_ (c) + { + names_ >> enumerator_; + } + + virtual Void + traverse (Type& e) + { + // First see if we should delegate this one to the Complex + // generator. + // + Type* base_enum (0); + + if (!enum_ || !enum_mapping (e, &base_enum)) + { + complex_.traverse (e); + return; + } + + SemanticGraph::Context& ec (e.context ()); + String const& name (ename_custom (e)); + + // We may not need to generate the class if this type is + // being customized. + // + if (name) + { + Boolean fl (fixed_length (e)); + Boolean cd (ec.count ("cd-name")); + Boolean poly (polymorphic (e)); + String const& vt (ec.get<String> ("value-type")); + + os << "// " << comment (e.name ()) << " (" << + (fl ? "fixed-length" : "variable-length") << ")" << endl + << "//" << endl; + + os << "class " << name; + + if (base_enum) + { + os << ": public "; + base_name_.dispatch (e.inherits ().base ()); + } + + os << "{"; + + if (!fl) + os << "private:" << endl + << name << " (const " << name << "&);" + << name << "& operator= (const " << name << "&);" + << endl; + + os << "public:" << endl; + + // value_type + // + if (base_enum) + { + os << "typedef "; + base_name_.dispatch (*base_enum); + os << "::" << base_enum->context ().get<String> ("value-type") << + " " << vt << ";" + << endl; + } + else + { + os << "enum " << vt + << "{"; + names<Enumeration> (e, names_, 0, 0, 0, &Enumeration::comma); + os << "};"; + } + + // c-tors + // + os << name << " ();" + << name << " (" << vt << ");" + << endl; + + // value (value_type) + // + if (!base_enum) + os << "void" << endl + << ec.get<String> ("value") << " (" << vt << ");" + << endl; + + // d-tor + // + if (poly) + os << "virtual" << endl + << "~" << name << " ();" + << endl; + + if (!base_enum) + { + // operator value() + // + // Name lookup differences in various compilers make generation + // of this operator outside of the class a really hard task. So + // we are going to make it always inline. + // + os << "operator " << vt << " () const" + << "{" + << "return " << ec.get<String> ("value-member") << ";" + << "}"; + + // string() + // + os << "const char*" << endl + << ec.get<String> ("string") << " () const;" + << endl; + } + + // Custom data. + // + if (cd) + { + String const& name (ecd_name (e)); + String const& sequence (ecd_sequence (e)); + String const& iterator (ecd_iterator (e)); + String const& const_iterator (ecd_const_iterator (e)); + + os << "// Custom data." << endl + << "//" << endl; + + // sequence & iterators + // + os << "typedef " << data_seq << " " << sequence << ";" + << "typedef " << sequence << "::iterator " << iterator << ";" + << "typedef " << sequence << "::const_iterator " << + const_iterator << ";" + << endl; + + // const seq& + // name () const + // + os << "const " << sequence << "&" << endl + << name << " () const;" + << endl; + + // seq& + // name () + // + os << sequence << "&" << endl + << name << " ();" + << endl; + } + + if (poly && typeinfo) + { + os << "// Type information." << endl + << "//" << endl; + + os << "static const " << + (stl ? "::std::string&" : "char*") << endl + << "_static_type ();" + << endl; + + os << "virtual const " << + (stl ? "::std::string&" : "char*") << endl + << "_dynamic_type () const;" + << endl; + } + + if (!base_enum || cd) + os << "private:" << endl; + + if (!base_enum) + os << vt << " " << ec.get<String> ("value-member") << ";"; + + if (cd) + os << ecd_sequence (e) << " " << ecd_member (e) << ";"; + + os << "};"; + } + + // Generate include for custom type. + // + if (ec.count ("name-include")) + { + close_ns (); + + os << "#include " << process_include_path ( + ec.get<String> ("name-include")) << endl + << endl; + + open_ns (); + } + } + + virtual Void + comma (Type&) + { + os << "," << endl; + } + + private: + Traversal::Complex& complex_; + TypeName base_name_; + + Traversal::Names names_; + Enumerator enumerator_; + }; + struct List : Traversal::List, Context { List (Context& c) @@ -2412,6 +2635,14 @@ namespace CXX os << "{"; + // copy c-tor & operator= (private) + // + if (!fl) + os << "private:" << endl + << name << " (const " << name << "&);" + << name << "& operator= (const " << name << "&);" + << endl; + // c-tor // os << "public:" << endl @@ -2422,19 +2653,13 @@ namespace CXX if (!restriction || poly) os << (poly ? "virtual\n" : "") << "~" << name << " ();"; - // copy c-tor & operator= + // copy c-tor & operator= (public) // - if (!fl) - os << endl - << "private:" << endl; - - if (!fl || !restriction) + if (fl && !restriction) os << name << " (const " << name << "&);" - << name << "& operator= (const " << name << "&);" - << endl; + << name << "& operator= (const " << name << "&);"; - if ((!restriction && !fl) || cd) - os << "public:" << endl; + os << endl; if (!restriction) { @@ -2614,7 +2839,7 @@ namespace CXX List list (ctx); Union union_ (ctx); Complex complex (ctx); - //Enumeration enumeration (ctx); + Enumeration enumeration (ctx, complex); schema >> sources >> schema; schema >> names_ns >> ns >> names; @@ -2622,7 +2847,7 @@ namespace CXX names >> list; names >> union_; names >> complex; - //names >> enumeration; + names >> enumeration; schema.dispatch (ctx.schema_root); } diff --git a/xsde/cxx/hybrid/tree-inline.cxx b/xsde/cxx/hybrid/tree-inline.cxx index 26b1a48..28a0582 100644 --- a/xsde/cxx/hybrid/tree-inline.cxx +++ b/xsde/cxx/hybrid/tree-inline.cxx @@ -15,6 +15,115 @@ namespace CXX { namespace { + struct Enumeration : Traversal::Enumeration, Context + { + Enumeration (Context& c, Traversal::Complex& complex) + : Context (c), + complex_ (complex), + base_name_ (c, TypeName::base) + { + } + + virtual Void + traverse (Type& e) + { + // First see if we should delegate this one to the Complex + // generator. + // + Type* base_enum (0); + + if (!enum_ || !enum_mapping (e, &base_enum)) + { + complex_.traverse (e); + return; + } + + String const& name (ename_custom (e)); + + // We may not need to generate the class if this type is + // being customized. + // + if (!name) + return; + + SemanticGraph::Context& ec (e.context ()); + String const& vt (ec.get<String> ("value-type")); + + os << "// " << comment (e.name ()) << endl + << "//" << endl + << endl; + + // c-tors + // + os << inl + << name << "::" << endl + << name << " ()" + << "{" + << "}"; + + os << inl + << name << "::" << endl + << name << " (" << vt << " v)" + << "{"; + + if (base_enum) + { + os << "this->" << base_enum->context ().get<String> ("value") << + " (v);"; + } + else + os << ec.get<String> ("value-member") << " = v;"; + + os << "}"; + + // value (value_type) + // + if (!base_enum) + { + os << inl + << "void " << name << "::" << endl + << ec.get<String> ("value") << " (" << vt << " v)" + << "{" + << ec.get<String> ("value-member") << " = v;" + << "}"; + } + + // Custom data. + // + if (ec.count ("cd-name")) + { + String const& cd_name (ecd_name (e)); + String const& member (ecd_member (e)); + String const& sequence (ecd_sequence (e)); + + // const seq& + // name () const + // + os << inl + << "const " << name << "::" << sequence << "& " << + name << "::" << endl + << cd_name << " () const" + << "{" + << "return this->" << member << ";" + << "}"; + + // seq& + // name () + // + os << inl + << name << "::" << sequence << "& " << name << "::" << endl + << cd_name << " ()" + << "{" + << "return this->" << member << ";" + << "}"; + } + } + + private: + Traversal::Complex& complex_; + TypeName base_name_; + }; + struct List : Traversal::List, Context { List (Context& c) @@ -2029,7 +2138,7 @@ namespace CXX List list (ctx); Union union_ (ctx); Complex complex (ctx); - //Enumeration enumeration (ctx); + Enumeration enumeration (ctx, complex); schema >> sources >> schema; schema >> names_ns >> ns >> names; @@ -2037,7 +2146,7 @@ namespace CXX names >> list; names >> union_; names >> complex; - //names >> enumeration; + names >> enumeration; schema.dispatch (ctx.schema_root); } diff --git a/xsde/cxx/hybrid/tree-name-processor.cxx b/xsde/cxx/hybrid/tree-name-processor.cxx index 240da59..e5c55db 100644 --- a/xsde/cxx/hybrid/tree-name-processor.cxx +++ b/xsde/cxx/hybrid/tree-name-processor.cxx @@ -4,6 +4,8 @@ // license : GNU GPL v2 + exceptions; see accompanying LICENSE file #include <cxx/elements.hxx> + +#include <cxx/hybrid/elements.hxx> #include <cxx/hybrid/tree-name-processor.hxx> #include <xsd-frontend/semantic-graph.hxx> @@ -51,6 +53,7 @@ namespace CXX schema_path (schema_path_), stl (!ops.value<CLI::no_stl> ()), detach (ops.value<CLI::generate_detach> ()), + enum_ (!ops.value<CLI::suppress_enum> ()), custom_data_map (custom_data_map_), custom_type_map (custom_type_map_), global_type_names (global_type_names_) @@ -179,6 +182,7 @@ namespace CXX schema_path (c.schema_path), stl (c.stl), detach (c.detach), + enum_ (c.enum_), custom_data_map (c.custom_data_map), custom_type_map (c.custom_type_map), global_type_names (c.global_type_names) @@ -279,6 +283,7 @@ namespace CXX Boolean stl; Boolean detach; + Boolean enum_; CustomDataMap& custom_data_map; CustomTypeMap& custom_type_map; @@ -1140,9 +1145,29 @@ namespace CXX // // + struct Enumerator: Traversal::Enumerator, Context + { + Enumerator (Context& c, NameSet& set) + : Context (c), set_ (set) + { + } + + virtual Void + traverse (Type& e) + { + e.context ().set ("name", find_name (e.name (), set_)); + } + + private: + NameSet& set_; + }; + + // + // struct GlobalTypeMembers: Traversal::List, Traversal::Union, Traversal::Complex, + Traversal::Enumeration, Context { GlobalTypeMembers (Context& c, Boolean data_members) @@ -1151,6 +1176,82 @@ namespace CXX } virtual Void + traverse (SemanticGraph::Enumeration& e) + { + // First see if we should delegate this one to Complex. + // + SemanticGraph::Enumeration* base_enum (0); + + if (!enum_ || !Hybrid::Context::enum_mapping (e, &base_enum)) + { + traverse (static_cast<SemanticGraph::Complex&> (e)); + return; + } + + SemanticGraph::Context& ec (e.context ()); + + // In case of customization use name-base instead of name. + // If name is empty then we are not generating anything. + // + String const& name (ec.count ("name-base") + ? ec.get<String> ("name-base") + : ec.get<String> ("name")); + if (!name) + return; + + if (!data_members_) + { + ec.set (member_set_key, NameSet ()); + NameSet& set (ec.get<NameSet> (member_set_key)); + set.insert (name); + + String v (ec.get<String> ("value-type")); // Set by GlobalTypeName. + set.insert (v); + + Enumerator enumerator (*this, set); + Traversal::Names names (enumerator); + Enumeration::names (e, names); + + if (!base_enum) + { + ec.set ("value", find_name ("value", set)); + ec.set ("string", find_name ("string", set)); + } + + // Check if this type has custom data. + // + CustomDataMap::Iterator i (custom_data_map.find (e.name ())); + + if (i != custom_data_map.end () && + i->second->find (L"") != i->second->end ()) + { + String name (find_name ("custom_data", set)); + + ec.set ("cd-name", name); + ec.set ("cd-sequence", find_name (name + L"_sequence", set)); + ec.set ("cd-iterator", find_name (name + L"_iterator", set)); + ec.set ("cd-const-iterator", + find_name (name + L"_const_iterator", set)); + } + } + else + { + NameSet& set (ec.get<NameSet> (member_set_key)); + + if (!base_enum) + ec.set ("value-member", find_name ("value_", set)); + + // Custom data. + // + if (ec.count ("cd-name")) + { + String const& base (ec.get<String> ("cd-name")); + ec.set ("cd-member", find_name (base + L"_", set)); + } + } + } + + virtual Void traverse (SemanticGraph::List& l) { SemanticGraph::Context& lc (l.context ()); @@ -1531,6 +1632,7 @@ namespace CXX // struct GlobalTypeName: Traversal::Type, Traversal::Union, + Traversal::Enumeration, Context { GlobalTypeName (Context& c, NameSet& set) @@ -1591,6 +1693,32 @@ namespace CXX uc.set ("value", find_name ("value", set)); } + virtual Void + traverse (SemanticGraph::Enumeration& e) + { + traverse (static_cast<SemanticGraph::Type&> (e)); + + if (enum_ && Hybrid::Context::enum_mapping (e)) + { + // We need to assign the value type name for enumerations + // even in included/imported schemas since we may need this + // information when generating derived enums. We need to do + // this even if the type is completely customized. + // + SemanticGraph::Context& ec (e.context ()); + String name (ec.count ("name-base") + ? ec.get<String> ("name-base") + : ec.get<String> ("name")); + + if (!name) + name = ec.get<String> ("name"); + + NameSet set; + set.insert (name); + ec.set ("value-type", find_name ("value_type", set)); + } + } + private: NameSet& set_; }; diff --git a/xsde/cxx/hybrid/tree-size-processor.cxx b/xsde/cxx/hybrid/tree-size-processor.cxx index 33d829a..c6b347e 100644 --- a/xsde/cxx/hybrid/tree-size-processor.cxx +++ b/xsde/cxx/hybrid/tree-size-processor.cxx @@ -237,20 +237,23 @@ namespace CXX // struct Type: Traversal::List, Traversal::Union, - Traversal::Complex + Traversal::Complex, + Traversal::Enumeration { Type (Boolean& valid, TypeSet& custom_data, CustomTypeMap& custom_type_map, TypeSet& poly_types, Boolean stl_, - Boolean poly_) + Boolean poly_, + Boolean enum_mapping) : valid_ (valid), custom_data_ (custom_data), custom_type_map_ (custom_type_map), poly_types_ (poly_types), stl (stl_), - poly (poly_) + poly (poly_), + enum_ (enum_mapping) { } @@ -281,6 +284,44 @@ namespace CXX } virtual Void + traverse (SemanticGraph::Enumeration& e) + { + if (!test (e)) + { + // First process our base since enum_mapping() needs the + // polymorphic property determined. + // + SemanticGraph::Type& b (e.inherits ().base ()); + + if (!test (b)) + dispatch (b); + + SemanticGraph::Enumeration* base_enum (0); + + if (!enum_ || !Context::enum_mapping (e, &base_enum)) + { + traverse (static_cast<SemanticGraph::Complex&> (e)); + return; + } + + Boolean fixed (true); + + if (base_enum && !get (b)) + fixed = false; + + // Check for custom data. + // + if (fixed) + { + if (custom_data_.find (e.name ()) != custom_data_.end ()) + fixed = false; + } + + set (e, fixed); + } + } + + virtual Void traverse (SemanticGraph::Complex& c) { SemanticGraph::Context& ctx (c.context ()); @@ -428,6 +469,7 @@ namespace CXX TypeSet& poly_types_; Boolean stl; Boolean poly; + Boolean enum_; typedef Containers::Vector<SemanticGraph::Complex*> Path; Path path_; @@ -1184,7 +1226,8 @@ namespace CXX custom_type_map, poly_types, stl, - poly); + poly, + !ops.value<CLI::suppress_enum> ()); schema >> schema_names >> ns >> ns_names >> type; diff --git a/xsde/cxx/hybrid/tree-source.cxx b/xsde/cxx/hybrid/tree-source.cxx index eb83658..61186b5 100644 --- a/xsde/cxx/hybrid/tree-source.cxx +++ b/xsde/cxx/hybrid/tree-source.cxx @@ -15,6 +15,135 @@ namespace CXX { namespace { + struct Enumerator: Traversal::Enumerator, Context + { + Enumerator (Context& c) + : Context (c) + { + } + + virtual Void + traverse (Type& e) + { + os << strlit (e.name ()); + } + }; + + struct Enumeration: Traversal::Enumeration, Context + { + Enumeration (Context& c, Traversal::Complex& complex) + : Context (c), complex_ (complex), enumerator_ (c) + { + names_ >> enumerator_; + } + + virtual Void + traverse (Type& e) + { + // First see if we should delegate this one to the Complex + // generator. + // + Type* base_enum (0); + + if (!enum_ || !enum_mapping (e, &base_enum)) + { + complex_.traverse (e); + return; + } + + String const& name (ename_custom (e)); + + // We may not need to generate the class if this type is + // being customized. + // + if (!name) + return; + + SemanticGraph::Context& ec (e.context ()); + + os << "// " << comment (e.name ()) << endl + << "//" << endl + << endl; + + if (!base_enum) + { + os << "static const char* _xsde_" << name << "_enumerators_[] = {"; + names<Enumeration> (e, names_, 0, 0, 0, &Enumeration::comma); + os << "};"; + + // string() + // + os << "const char* " << name << "::" << endl + << ec.get<String> ("string") << " () const" + << "{" + << "return _xsde_" << name << "_enumerators_[" << + ec.get<String> ("value-member") << "];" + << "}"; + } + + if (polymorphic (e)) + { + // d-tor + // + os << name << "::" << endl + << "~" << name << " ()" + << "{" + << "}"; + + if (typeinfo) + { + String id (e.name ()); + + if (String ns = xml_ns_name (e)) + { + id += L' '; + id += ns; + } + + if (stl) + { + os << "static const ::std::string _xsde_" << name << + "_static_type_ = " << strlit (id) << ";" + << endl; + + os << "const ::std::string& " << name << "::" << endl + << "_static_type ()" + << "{" + << "return _xsde_" << name << "_static_type_;" + << "}"; + } + else + { + os << "const char* " << name << "::" << endl + << "_static_type ()" + << "{" + << "return " << strlit (id) << ";" + << "}"; + } + + os << "const " << (stl ? "::std::string& " : "char* ") << + name << "::" << endl + << "_dynamic_type () const" + << "{" + << "return _static_type ();" + << "}"; + } + } + } + + virtual Void + comma (Type&) + { + os << "," << endl; + } + + private: + Traversal::Complex& complex_; + + Traversal::Names names_; + Enumerator enumerator_; + }; + struct List : Traversal::List, Context { List (Context& c) @@ -1968,6 +2097,7 @@ namespace CXX List list (ctx); Union union_ (ctx); Complex complex (ctx); + Enumeration enumeration (ctx, complex); schema >> sources >> schema; schema >> names_ns >> ns >> names; @@ -1975,6 +2105,7 @@ namespace CXX names >> list; names >> union_; names >> complex; + names >> enumeration; schema.dispatch (ctx.schema_root); } |