From 4f38adc11ab1a3a1ab2dd3f958c917182be7d71f Mon Sep 17 00:00:00 2001 From: Boris Kolpackov Date: Thu, 7 Oct 2010 14:48:13 +0200 Subject: Implement generation of clone functions New test: clone. --- xsde/cxx/hybrid/cli.hxx | 2 + xsde/cxx/hybrid/elements.cxx | 1 + xsde/cxx/hybrid/elements.hxx | 70 +++ xsde/cxx/hybrid/generator.cxx | 6 + xsde/cxx/hybrid/tree-header.cxx | 234 ++++++-- xsde/cxx/hybrid/tree-source.cxx | 1257 ++++++++++++++++++++++++++++++++++++--- 6 files changed, 1453 insertions(+), 117 deletions(-) (limited to 'xsde/cxx/hybrid') diff --git a/xsde/cxx/hybrid/cli.hxx b/xsde/cxx/hybrid/cli.hxx index 5de1692..5d691d6 100644 --- a/xsde/cxx/hybrid/cli.hxx +++ b/xsde/cxx/hybrid/cli.hxx @@ -36,6 +36,7 @@ namespace CXX extern Key suppress_serializer_val; extern Key omit_default_attributes; extern Key suppress_enum; + extern Key generate_clone; extern Key generate_detach; extern Key generate_insertion; extern Key generate_extraction; @@ -127,6 +128,7 @@ namespace CXX suppress_serializer_val, Boolean, omit_default_attributes, Boolean, suppress_enum, Boolean, + generate_clone, Boolean, generate_detach, Boolean, generate_insertion, Cult::Containers::Vector, generate_extraction, Cult::Containers::Vector, diff --git a/xsde/cxx/hybrid/elements.cxx b/xsde/cxx/hybrid/elements.cxx index fe5c97e..b8c109a 100644 --- a/xsde/cxx/hybrid/elements.cxx +++ b/xsde/cxx/hybrid/elements.cxx @@ -40,6 +40,7 @@ namespace CXX poly_code (ops.value ()), poly_runtime (poly_code || ops.value ()), reset (!ops.value ()), + clone (ops.value ()), detach (ops.value ()), mixin (ops.value ()), tiein (!mixin), diff --git a/xsde/cxx/hybrid/elements.hxx b/xsde/cxx/hybrid/elements.hxx index 60211e8..7bd8bd1 100644 --- a/xsde/cxx/hybrid/elements.hxx +++ b/xsde/cxx/hybrid/elements.hxx @@ -45,6 +45,7 @@ namespace CXX poly_code (c.poly_code), poly_runtime (c.poly_runtime), reset (c.reset), + clone (c.clone), detach (c.detach), typeinfo (c.typeinfo), mixin (c.mixin), @@ -76,6 +77,7 @@ namespace CXX poly_code (c.poly_code), poly_runtime (c.poly_runtime), reset (c.reset), + clone (c.clone), detach (c.detach), typeinfo (c.typeinfo), mixin (c.mixin), @@ -594,6 +596,7 @@ namespace CXX Boolean poly_code; Boolean poly_runtime; Boolean reset; + Boolean clone; Boolean detach; Boolean typeinfo; Boolean mixin; @@ -2060,6 +2063,73 @@ namespace CXX // // + struct TypeClone: TypeOpsBase, Context + { + TypeClone (Context& c) + : Context (c) + { + } + + // Copy member from 'this' to 'c'. + // + Void + dispatch (SemanticGraph::Node& type, SemanticGraph::Member& member) + { + member_ = &member; + Traversal::NodeBase::dispatch (type); + } + + protected: + virtual Void + type (SemanticGraph::Type& t) + { + String const& name (ename (*member_)); + + os << "{" + << fq_name (t) << "* m = this->" << name << " ()._clone ();"; + + if (!exceptions) + os << endl + << "if (m == 0)" << endl + << "return false;" + << endl; + + os << "c." << name << " (m);" + << "}"; + } + + virtual Void + fund_type (SemanticGraph::Type& t) + { + type (t); + } + + virtual Void + string_type (SemanticGraph::Type&) + { + // We can only get here if STL is disabled. + // + String const& name (ename (*member_)); + + os << "{" + << "char* m = ::xsde::cxx::strdupx (this->" << name << " ());"; + + if (!exceptions) + os << endl + << "if (m == 0)" << endl + << "return false;" + << endl; + + os << "c." << name << " (m);" + << "}"; + } + + private: + SemanticGraph::Member* member_; + }; + + // + // struct TypeForward: Traversal::Type, Context { TypeForward (Context& c) diff --git a/xsde/cxx/hybrid/generator.cxx b/xsde/cxx/hybrid/generator.cxx index 0ccbb91..ee39079 100644 --- a/xsde/cxx/hybrid/generator.cxx +++ b/xsde/cxx/hybrid/generator.cxx @@ -124,6 +124,7 @@ namespace CXX 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_clone = "generate-clone"; extern Key generate_detach = "generate-detach"; extern Key generate_insertion = "generate-insertion"; extern Key generate_extraction = "generate-extraction"; @@ -271,6 +272,11 @@ namespace CXX << " enumeration to C++ enum mapping." << endl; + e << "--generate-clone" << endl + << " Generate clone functions for variable-length\n" + << " types." + << endl; + e << "--generate-detach" << endl << " Generate detach functions for elements and\n" << " attributes of variable-length types." diff --git a/xsde/cxx/hybrid/tree-header.cxx b/xsde/cxx/hybrid/tree-header.cxx index 7e748bb..c596ab0 100644 --- a/xsde/cxx/hybrid/tree-header.cxx +++ b/xsde/cxx/hybrid/tree-header.cxx @@ -112,6 +112,13 @@ namespace CXX << name << " (" << vt << ");" << endl; + // _clone + // + if (!fl && clone) + os << (poly ? "virtual " : "") << name << "*" << endl + << "_clone () const;" + << endl; + // value (value_type) // if (!base_enum) @@ -197,6 +204,13 @@ namespace CXX << endl; } + // _copy + // + if (!fl && clone) + os << (exceptions ? "void" : "bool") << endl + << "_copy (" << name << "&) const;" + << endl; + if (!base_enum || cd) os << "private:" << endl; @@ -274,15 +288,22 @@ namespace CXX // c-tor // os << "public:" << endl - << name << " ();"; + << name << " ();" + << endl; + + // _clone + // + if (clone) + os << (poly ? "virtual " : "") << name << "*" << endl + << "_clone () const;" + << endl; // d-tor // if (poly) os << "virtual" << endl - << "~" << name << " ();"; - - os << endl; + << "~" << name << " ();" + << endl; // Custom data. // @@ -335,6 +356,13 @@ namespace CXX << endl; } + // _copy + // + if (clone) + os << (exceptions ? "void" : "bool") << endl + << "_copy (" << name << "&) const;" + << endl; + if (cd) { os << "private:" << endl @@ -401,7 +429,15 @@ namespace CXX // c-tor // - os << name << " ();"; + os << name << " ();" + << endl; + + // _clone + // + if (!fl && clone) + os << (poly ? "virtual " : "") << name << "*" << endl + << "_clone () const;" + << endl; // d-tor // @@ -521,6 +557,13 @@ namespace CXX << endl; } + // _copy + // + if (!fl && clone) + os << (exceptions ? "void" : "bool") << endl + << "_copy (" << name << "&) const;" + << endl; + if (stl) { os << "private:" << endl @@ -634,7 +677,7 @@ namespace CXX belongs_ >> *this; } - // Type alignment ranking (the high the rank, the stricter + // Type alignment ranking (the higher the rank, the stricter // the alignment requirements): // // char 1 @@ -1315,7 +1358,7 @@ namespace CXX traverse (SemanticGraph::Attribute& a) { os << "// " << comment (a.name ()) << endl - << "// " << endl; + << "//" << endl; Boolean def (a.default_p ()); Boolean fix (a.fixed_p ()); @@ -1413,7 +1456,7 @@ namespace CXX traverse (SemanticGraph::Element& e) { os << "// " << comment (e.name ()) << endl - << "// " << endl; + << "//" << endl; String const& name (ename (e)); SemanticGraph::Type& t (e.type ()); @@ -1535,22 +1578,33 @@ namespace CXX os << "// " << comment (name) << " (" << (fl ? "fixed-length" : "variable-length") << ")" << endl - << "// " << endl; + << "//" << endl; os << "class " << type << "{"; - // c-tor & d-tor + // c-tor // os << "public:" << endl << type << " ();" - << "~" << type << " ();"; + << endl; + + // _clone + // + if (!fl && clone) + os << type << "*" << endl + << "_clone () const;" + << endl; + + // d-tor + // + os << "~" << type << " ();" + << endl; // copy c-tor & operator= // if (!fl) - os << endl - << "private:" << endl; + os << "private:" << endl; os << type << " (const " << type << "&);" << type << "& operator= (const " << type << "&);" @@ -1596,6 +1650,13 @@ namespace CXX << endl; } + // _copy + // + if (!fl && clone) + os << (exceptions ? "void" : "bool") << endl + << "_copy (" << type << "&) const;" + << endl; + os << "private:" << endl; All::contains (a, contains_data_); @@ -1739,22 +1800,33 @@ namespace CXX os << "// " << comment (name) << " (" << (fl ? "fixed-length" : "variable-length") << ")" << endl - << "// " << endl; + << "//" << endl; os << "class " << type << "{"; - // c-tor & d-tor + // c-tor // os << "public:" << endl << type << " ();" - << "~" << type << " ();"; + << endl; + + // _clone + // + if (!fl && clone) + os << type << "*" << endl + << "_clone () const;" + << endl; + + // d-tor + // + os << "~" << type << " ();" + << endl; // copy c-tor & operator= // if (!fl) - os << endl - << "private:" << endl; + os << "private:" << endl; os << type << " (const " << type << "&);" << type << "& operator= (const " << type << "&);" @@ -1766,7 +1838,7 @@ namespace CXX else { os << "// " << comment (name) << endl - << "// " << endl; + << "//" << endl; } String const& arm_tag (earm_tag (c)); @@ -1838,6 +1910,13 @@ namespace CXX << endl; } + // _copy + // + if (!fl && clone) + os << (exceptions ? "void" : "bool") << endl + << "_copy (" << type << "&) const;" + << endl; + os << "private:" << endl << "union" << "{"; @@ -1967,22 +2046,33 @@ namespace CXX os << "// " << comment (name) << " (" << (fl ? "fixed-length" : "variable-length") << ")" << endl - << "// " << endl; + << "//" << endl; os << "class " << type << "{"; - // c-tor & d-tor + // c-tor // os << "public:" << endl << type << " ();" - << "~" << type << " ();"; + << endl; + + // _clone + // + if (!fl && clone) + os << type << "*" << endl + << "_clone () const;" + << endl; + + // d-tor + // + os << "~" << type << " ();" + << endl; // copy c-tor & operator= // if (!fl) - os << endl - << "private:" << endl; + os << "private:" << endl; os << type << " (const " << type << "&);" << type << "& operator= (const " << type << "&);" @@ -2056,6 +2146,13 @@ namespace CXX << endl; } + // _copy + // + if (!fl && clone) + os << (exceptions ? "void" : "bool") << endl + << "_copy (" << type << "&) const;" + << endl; + os << "private:" << endl << "union" << "{"; @@ -2190,22 +2287,33 @@ namespace CXX os << "// " << comment (name) << " (" << (fl ? "fixed-length" : "variable-length") << ")" << endl - << "// " << endl; + << "//" << endl; os << "class " << type << "{"; - // c-tor & d-tor + // c-tor // os << "public:" << endl << type << " ();" - << "~" << type << " ();"; + << endl; + + // _clone + // + if (!fl && clone) + os << type << "*" << endl + << "_clone () const;" + << endl; + + // d-tor + // + os << "~" << type << " ();" + << endl; // copy c-tor & operator= // if (!fl) - os << endl - << "private:" << endl; + os << "private:" << endl; os << type << " (const " << type << "&);" << type << "& operator= (const " << type << "&);" @@ -2251,6 +2359,13 @@ namespace CXX << endl; } + // _copy + // + if (!fl && clone) + os << (exceptions ? "void" : "bool") << endl + << "_copy (" << type << "&) const;" + << endl; + os << "private:" << endl; Sequence::contains (s, contains_data_); @@ -2372,22 +2487,33 @@ namespace CXX os << "// " << comment (name) << " (" << (fl ? "fixed-length" : "variable-length") << ")" << endl - << "// " << endl; + << "//" << endl; os << "class " << type << "{"; - // c-tor & d-tor + // c-tor // os << "public:" << endl << type << " ();" - << "~" << type << " ();"; + << endl; + + // _clone + // + if (!fl && clone) + os << type << "*" << endl + << "_clone () const;" + << endl; + + // d-tor + // + os << "~" << type << " ();" + << endl; // copy c-tor & operator= // if (!fl) - os << endl - << "private:" << endl; + os << "private:" << endl; os << type << " (const " << type << "&);" << type << "& operator= (const " << type << "&);" @@ -2431,6 +2557,13 @@ namespace CXX << endl; } + // _copy + // + if (!fl && clone) + os << (exceptions ? "void" : "bool") << endl + << "_copy (" << type << "&) const;" + << endl; + os << "private:" << endl; Sequence::contains (s, contains_data_); @@ -2533,7 +2666,7 @@ namespace CXX Traversal::ContainsParticle& contains_data_; }; - struct Complex : Traversal::Complex, Context + struct Complex: Traversal::Complex, Context { Complex (Context& c) : Context (c), @@ -2646,20 +2779,28 @@ namespace CXX // c-tor // os << "public:" << endl - << name << " ();"; - - // d-tor - // - if (!restriction || poly) - os << (poly ? "virtual\n" : "") << "~" << name << " ();"; + << name << " ();" + << endl; // copy c-tor & operator= (public) // if (fl && !restriction) os << name << " (const " << name << "&);" - << name << "& operator= (const " << name << "&);"; + << name << "& operator= (const " << name << "&);" + << endl; - os << endl; + // _clone + // + if (!fl && clone) + os << (poly ? "virtual " : "") << name << "*" << endl + << "_clone () const;" + << endl; + + // d-tor + // + if (!restriction || poly) + os << (poly ? "virtual\n" : "") << "~" << name << " ();" + << endl; if (!restriction) { @@ -2720,6 +2861,13 @@ namespace CXX << endl; } + // _copy + // + if (!fl && clone) + os << (exceptions ? "void" : "bool") << endl + << "_copy (" << name << "&) const;" + << endl; + if (!restriction || cd) os << "private:" << endl; diff --git a/xsde/cxx/hybrid/tree-source.cxx b/xsde/cxx/hybrid/tree-source.cxx index 5887d32..33995c5 100644 --- a/xsde/cxx/hybrid/tree-source.cxx +++ b/xsde/cxx/hybrid/tree-source.cxx @@ -32,7 +32,10 @@ namespace CXX struct Enumeration: Traversal::Enumeration, Context { Enumeration (Context& c, Traversal::Complex& complex) - : Context (c), complex_ (complex), enumerator_ (c) + : Context (c), + complex_ (complex), + base_name_ (c, TypeName::base), + enumerator_ (c) { names_ >> enumerator_; } @@ -129,6 +132,123 @@ namespace CXX << "}"; } } + + // _clone + // + if (clone && !fixed_length (e)) + { + // + // _copy + // + + os << (exceptions ? "void " : "bool ") << name << "::" << endl + << "_copy (" << name << "& c) const" + << "{"; + + // Copy the base or enum value. + // + if (base_enum) + { + SemanticGraph::Type& b (e.inherits ().base ()); + + if (fixed_length (b)) + { + os << "static_cast< "; + base_name_.dispatch (b); + os << "& > (c) = *this;"; + } + else + { + os << "const "; + base_name_.dispatch (b); + os << "& b = *this;"; + + if (exceptions) + os << "b._copy (c);"; + else + os << "if (!b._copy (c))" << endl + << "return false;" + << endl; + } + } + else + { + String const& m (ec.get ("value-member")); + os << "c." << m << " = this->" << m << ";"; + } + + // Copy custom data. + // + if (ec.count ("cd-name")) + { + String const& m (ecd_member (e)); + + if (exceptions) + os << "this->" << m << ".copy (c." << m << ");"; + else + os << "if (this->" << m << ".copy (c." << m << "))" << endl + << "return false;" + << endl; + } + + if (!exceptions) + os << "return true;"; + + os << "}"; + + // + // _clone + // + + os << name << "* " << name << "::" << endl + << "_clone () const" + << "{"; + + if (!custom_alloc) + os << name << "* c = new " << name << ";"; + else + os << name << "* c = static_cast< " << name << "* > (" << endl + << "::xsde::cxx::alloc (sizeof (" << name << ")));"; + + if (!exceptions) + os << endl + << "if (c == 0)" << endl + << "return 0;" + << endl; + + if (custom_alloc) + { + if (exceptions) + os << "::xsde::cxx::alloc_guard ag (c);"; + + os << "new (c) " << name << ";"; + + if (exceptions) + os << "ag.release ();"; + } + + if (exceptions) + os << "::xsde::cxx::guard< " << name << " > g (c);" + << "this->_copy (*c);" + << "g.release ();"; + else + { + os << "if (!this->_copy (*c))" + << "{"; + + if (!custom_alloc) + os << "delete c;"; + else + os << "c->~" << name << " ();" + << "::xsde::cxx::free (c);"; + + os << "return 0;" + << "}"; + } + + os << "return c;" + << "}"; + } } virtual Void @@ -140,6 +260,8 @@ namespace CXX private: Traversal::Complex& complex_; + TypeName base_name_; + Traversal::Names names_; Enumerator enumerator_; }; @@ -147,7 +269,7 @@ namespace CXX struct List : Traversal::List, Context { List (Context& c) - : Context (c) + : Context (c), base_name_ (c, TypeName::seq) { } @@ -162,12 +284,16 @@ namespace CXX if (!name) return; - if (polymorphic (l)) - { + Boolean poly (polymorphic (l)); + SemanticGraph::Context& lc (l.context ()); + + if (poly || clone) os << "// " << comment (l.name ()) << endl << "//" << endl << endl; + if (poly) + { // d-tor // os << name << "::" << endl @@ -214,7 +340,108 @@ namespace CXX << "}"; } } + + // _clone + // + if (clone) + { + // + // _copy + // + + os << (exceptions ? "void " : "bool ") << name << "::" << endl + << "_copy (" << name << "& c) const" + << "{"; + + // Copy the base. + // + os << "const "; + base_name_.dispatch (l.argumented ().type ()); + os << "& b = *this;"; + + if (exceptions) + os << "b.copy (c);"; + else + os << "if (b.copy (c))" << endl + << "return false;" + << endl; + + // Copy custom data. + // + if (lc.count ("cd-name")) + { + String const& m (ecd_member (l)); + + if (exceptions) + os << "this->" << m << ".copy (c." << m << ");"; + else + os << "if (this->" << m << ".copy (c." << m << "))" << endl + << "return false;" + << endl; + } + + if (!exceptions) + os << "return true;"; + + os << "}"; + + // + // _clone + // + + os << name << "* " << name << "::" << endl + << "_clone () const" + << "{"; + + if (!custom_alloc) + os << name << "* c = new " << name << ";"; + else + os << name << "* c = static_cast< " << name << "* > (" << endl + << "::xsde::cxx::alloc (sizeof (" << name << ")));"; + + if (!exceptions) + os << endl + << "if (c == 0)" << endl + << "return 0;" + << endl; + + if (custom_alloc) + { + if (exceptions) + os << "::xsde::cxx::alloc_guard ag (c);"; + + os << "new (c) " << name << ";"; + + if (exceptions) + os << "ag.release ();"; + } + + if (exceptions) + os << "::xsde::cxx::guard< " << name << " > g (c);" + << "this->_copy (*c);" + << "g.release ();"; + else + { + os << "if (!this->_copy (*c))" + << "{"; + + if (!custom_alloc) + os << "delete c;"; + else + os << "c->~" << name << " ();" + << "::xsde::cxx::free (c);"; + + os << "return 0;" + << "}"; + } + + os << "return c;" + << "}"; + } } + + private: + TypeName base_name_; }; // @@ -238,13 +465,14 @@ namespace CXX return; Boolean poly (polymorphic (u)); + SemanticGraph::Context& uc (u.context ()); + + os << "// " << comment (u.name ()) << endl + << "//" << endl + << endl; if (!stl || poly) { - os << "// " << comment (u.name ()) << endl - << "//" << endl - << endl; - // d-tor // os << name << "::" << endl @@ -302,6 +530,108 @@ namespace CXX << "}"; } } + + // _clone + // + if (clone && !fixed_length (u)) + { + // + // _copy + // + + os << (exceptions ? "void " : "bool ") << name << "::" << endl + << "_copy (" << name << "& c) const" + << "{"; + + // Copy the value. + // + String const& m (uc.get ("value-member")); + + if (stl) + os << "c." << m << " = this->" << m << ";"; + else + { + os << "c." << m << " = ::xsde::cxx::strdupx (this->" << m << ");"; + + if (!exceptions) + os << endl + << "if (c." << m << " == 0)" << endl + << "return false;" + << endl; + } + + // Copy custom data. + // + if (uc.count ("cd-name")) + { + String const& m (ecd_member (u)); + + if (exceptions) + os << "this->" << m << ".copy (c." << m << ");"; + else + os << "if (this->" << m << ".copy (c." << m << "))" << endl + << "return false;" + << endl; + } + + if (!exceptions) + os << "return true;"; + + os << "}"; + + // + // _clone + // + + os << name << "* " << name << "::" << endl + << "_clone () const" + << "{"; + + if (!custom_alloc) + os << name << "* c = new " << name << ";"; + else + os << name << "* c = static_cast< " << name << "* > (" << endl + << "::xsde::cxx::alloc (sizeof (" << name << ")));"; + + if (!exceptions) + os << endl + << "if (c == 0)" << endl + << "return 0;" + << endl; + + if (custom_alloc) + { + if (exceptions) + os << "::xsde::cxx::alloc_guard ag (c);"; + + os << "new (c) " << name << ";"; + + if (exceptions) + os << "ag.release ();"; + } + + if (exceptions) + os << "::xsde::cxx::guard< " << name << " > g (c);" + << "this->_copy (*c);" + << "g.release ();"; + else + { + os << "if (!this->_copy (*c))" + << "{"; + + if (!custom_alloc) + os << "delete c;"; + else + os << "c->~" << name << " ();" + << "::xsde::cxx::free (c);"; + + os << "return 0;" + << "}"; + } + + os << "return c;" + << "}"; + } } }; @@ -1379,92 +1709,503 @@ namespace CXX }; // - // Nested classes. + // Clone. // - struct All: Traversal::All, Context + struct AttributeClone: Traversal::Attribute, Context { - All (Context& c, - Traversal::ContainsParticle& contains_ctor, - Traversal::ContainsParticle& contains_dtor, - Traversal::ContainsParticle& contains_copy, - Traversal::ContainsParticle& contains_assign) - : Context (c), - contains_ctor_ (contains_ctor), - contains_dtor_ (contains_dtor), - contains_copy_ (contains_copy), - contains_assign_ (contains_assign) + AttributeClone (Context& c) + : Context (c), clone_ (c) { } virtual Void - traverse (SemanticGraph::All& a) + traverse (SemanticGraph::Attribute& a) { - // For the all compositor, maxOccurs=1 and minOccurs={0,1} - // and it can only contain particles. - // - if (a.min () == 0) + if (!a.fixed_p ()) { - String const& type (etype (a)); - String const& scope (Context::scope (a)); - - // c-tor - // - os << scope << "::" << type << "::" << endl - << type << " ()" - << "{"; + String const& name (ename (a)); + SemanticGraph::Type& t (a.type ()); - All::contains (a, contains_ctor_); + Boolean opt (a.optional_p () && !a.default_p ()); - os << "}"; + if (opt) + os << "if (this->" << epresent (a) << " ())"; - // d-tor - // - os << scope << "::" << type << "::" << endl - << "~" << type << " ()" - << "{"; + if (fixed_length (t)) + os << (opt ? "\n" : "") + << "c." << name << " (this->" << name << " ());" + << endl; + else + clone_.dispatch (t, a); + } + } - All::contains (a, contains_dtor_); + private: + TypeClone clone_; + }; - os << "}"; - if (fixed_length (a)) - { - // copy c-tor - // - os << scope << "::" << type << "::" << endl - << type << " (const " << type << "& x)" - << "{" - << "XSDE_UNUSED (x);"; + struct ElementClone: Traversal::Element, Context + { + ElementClone (Context& c) + : Context (c), clone_ (c) + { + } - All::contains (a, contains_copy_); + virtual Void + traverse (SemanticGraph::Element& e) + { + String const& name (ename (e)); - os << "}"; + if (e.max () != 1) + { + if (exceptions) + os << "this->" << name << " ().copy (c." << name << " ());" + << endl; + else + os << "if (this->" << name << " ().copy (c." << name << " ()))" << endl + << "return false;" + << endl; + } + else + { + SemanticGraph::Type& t (e.type ()); - // operator= - // - os << scope << "::" << type << "& " << scope << "::" << - type << "::" << endl - << "operator= (const " << type << "& x)" - << "{" - << "XSDE_UNUSED (x);"; + Boolean opt (e.min () == 0); - All::contains (a, contains_assign_); + if (opt) + os << "if (this->" << epresent (e) << " ())"; - os << "return *this;" - << "}"; - } + if (fixed_length (t)) + os << (opt ? "\n" : "") + << "c." << name << " (this->" << name << " ());" + << endl; + else + clone_.dispatch (t, e); } } private: - Traversal::ContainsParticle& contains_ctor_; - Traversal::ContainsParticle& contains_dtor_; - Traversal::ContainsParticle& contains_copy_; - Traversal::ContainsParticle& contains_assign_; + TypeClone clone_; }; - struct Choice: Traversal::Choice, Context + struct AllClone: Traversal::All, Context + { + AllClone (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)); + + os << "if (this->" << epresent (a) << " ())"; + + if (fixed_length (a)) + os << endl + << "c." << name << " (this->" << name << " ());" + << endl; + else + { + os << "{" + << etype (a) << "* m = this->" << name << " ()._clone ();"; + + if (!exceptions) + os << endl + << "if (m == 0)" << endl + << "return false;" + << endl; + + os << "c." << name << " (m);" + << "}"; + } + } + else + All::contains (a); + } + }; + + struct SequenceInSequenceClone: Traversal::Sequence, Context + { + SequenceInSequenceClone (Context& c) + : Context (c) + { + } + + virtual Void + traverse (SemanticGraph::Sequence& s) + { + if (s.max () != 1) + { + String const& name (ename (s)); + + if (exceptions) + os << "this->" << name << " ().copy (c." << name << " ());" + << endl; + else + os << "if (this->" << name << " ().copy (c." << name << " ()))" << endl + << "return false;" + << endl; + } + else if (s.min () == 0) + { + String const& name (ename (s)); + + os << "if (this->" << epresent (s) << " ())"; + + if (fixed_length (s)) + os << endl + << "c." << name << " (this->" << name << " ());" + << endl; + else + { + os << "{" + << etype (s) << "* m = this->" << name << " ()._clone ();"; + + if (!exceptions) + os << endl + << "if (m == 0)" << endl + << "return false;" + << endl; + + os << "c." << name << " (m);" + << "}"; + } + } + else + Sequence::contains (s); + } + }; + + struct ParticleInChoiceClone: ElementClone, Traversal::Compositor + { + ParticleInChoiceClone (Context& c) + : ElementClone (c) + { + } + + virtual Void + traverse (SemanticGraph::Element& e) + { + os << "case " << etag (e) << ":" + << "{"; + + ElementClone::traverse (e); + + os << "break;" + << "}"; + } + + virtual Void + traverse (SemanticGraph::Compositor& c) + { + // In choice there are no inline compositors. + // + os << "case " << etag (c) << ":" + << "{"; + + String const& name (ename (c)); + + if (c.max () != 1) + { + if (exceptions) + os << "this->" << name << " ().copy (c." << name << " ());"; + else + os << "if (this->" << name << " ().copy (c." << name << " ()))" << endl + << "return false;"; + } + else + { + Boolean opt (c.min () == 0); + + if (opt) + os << "if (this->" << epresent (c) << " ())"; + + if (fixed_length (c)) + os << (opt ? "\n" : "") + << "c." << name << " (this->" << name << " ());" + << endl; + else + { + os << "{" + << etype (c) << "* m = this->" << name << " ()._clone ();"; + + if (!exceptions) + os << endl + << "if (m == 0)" << endl + << "return false;" + << endl; + + os << "c." << name << " (m);" + << "}"; + } + } + + os << "break;" + << "}"; + } + }; + + struct ChoiceInSequenceClone: Traversal::Choice, Context + { + ChoiceInSequenceClone (Context& c) + : Context (c), particle_ (c) + { + contains_particle_ >> particle_; + } + + virtual Void + traverse (SemanticGraph::Choice& c) + { + if (c.max () != 1) + { + String const& name (ename (c)); + + if (exceptions) + os << "this->" << name << " ().copy (c." << name << " ());" + << endl; + else + os << "if (this->" << name << " ().copy (c." << name << " ()))" << endl + << "return false;" + << endl; + } + else if (c.min () == 0) + { + String const& name (ename (c)); + + os << "if (this->" << epresent (c) << " ())"; + + if (fixed_length (c)) + os << endl + << "c." << name << " (this->" << name << " ());" + << endl; + else + { + os << "{" + << etype (c) << "* m = this->" << name << " ()._clone ();"; + + if (!exceptions) + os << endl + << "if (m == 0)" << endl + << "return false;" + << endl; + + os << "c." << name << " (m);" + << "}"; + } + } + else + { + // Inline choice. + // + String const& arm (earm (c)); + + os << "c." << arm << " (this->" << arm << " ());" + << endl + << "switch (this->" << arm << " ())" + << "{"; + + Choice::contains (c, contains_particle_); + + os << "default:" << endl + << "break;" + << "}"; + } + } + + private: + ParticleInChoiceClone particle_; + Traversal::ContainsParticle contains_particle_; + }; + + // + // Nested classes. + // + + struct All: Traversal::All, Context + { + All (Context& c, + Traversal::ContainsParticle& contains_ctor, + Traversal::ContainsParticle& contains_dtor, + Traversal::ContainsParticle& contains_copy, + Traversal::ContainsParticle& contains_assign, + Traversal::ContainsParticle& contains_clone) + : Context (c), + contains_ctor_ (contains_ctor), + contains_dtor_ (contains_dtor), + contains_copy_ (contains_copy), + contains_assign_ (contains_assign), + contains_clone_ (contains_clone) + { + } + + 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) + return; + + Boolean fl (fixed_length (a)); + String const& type (etype (a)); + String const& scope (Context::scope (a)); + + // c-tor + // + os << scope << "::" << type << "::" << endl + << type << " ()" + << "{"; + + All::contains (a, contains_ctor_); + + os << "}"; + + // d-tor + // + os << scope << "::" << type << "::" << endl + << "~" << type << " ()" + << "{"; + + All::contains (a, contains_dtor_); + + os << "}"; + + if (fl) + { + // copy c-tor + // + os << scope << "::" << type << "::" << endl + << type << " (const " << type << "& x)" + << "{" + << "XSDE_UNUSED (x);"; + + All::contains (a, contains_copy_); + + os << "}"; + + // operator= + // + os << scope << "::" << type << "& " << scope << "::" << + type << "::" << endl + << "operator= (const " << type << "& x)" + << "{" + << "XSDE_UNUSED (x);"; + + All::contains (a, contains_assign_); + + os << "return *this;" + << "}"; + } + + // _clone + // + if (!fl && clone) + { + // + // _copy + // + + os << (exceptions ? "void " : "bool ") << scope << "::" << + type << "::" << endl + << "_copy (" << type << "& c) const" + << "{"; + + All::contains (a, contains_clone_); + + // Copy custom data. + // + if (a.context ().count ("cd-name")) + { + String const& m (ecd_member (a)); + + if (exceptions) + os << "this->" << m << ".copy (c." << m << ");"; + else + os << "if (this->" << m << ".copy (c." << m << "))" << endl + << "return false;" + << endl; + } + + if (!exceptions) + os << "return true;"; + + os << "}"; + + // + // _clone + // + + os << scope << "::" << type << "* " << scope << "::" << + type << "::" << endl + << "_clone () const" + << "{"; + + if (!custom_alloc) + os << type << "* c = new " << type << ";"; + else + os << type << "* c = static_cast< " << type << "* > (" << endl + << "::xsde::cxx::alloc (sizeof (" << type << ")));"; + + if (!exceptions) + os << endl + << "if (c == 0)" << endl + << "return 0;" + << endl; + + if (custom_alloc) + { + if (exceptions) + os << "::xsde::cxx::alloc_guard ag (c);"; + + os << "new (c) " << type << ";"; + + if (exceptions) + os << "ag.release ();"; + } + + if (exceptions) + os << "::xsde::cxx::guard< " << type << " > g (c);" + << "this->_copy (*c);" + << "g.release ();"; + else + { + os << "if (!this->_copy (*c))" + << "{"; + + if (!custom_alloc) + os << "delete c;"; + else + os << "c->~" << type << " ();" + << "::xsde::cxx::free (c);"; + + os << "return 0;" + << "}"; + } + + os << "return c;" + << "}"; + } + } + + private: + Traversal::ContainsParticle& contains_ctor_; + Traversal::ContainsParticle& contains_dtor_; + Traversal::ContainsParticle& contains_copy_; + Traversal::ContainsParticle& contains_assign_; + Traversal::ContainsParticle& contains_clone_; + }; + + struct Choice: Traversal::Choice, Context { Choice (Context& c, Boolean in_choice, @@ -1475,12 +2216,14 @@ namespace CXX particle_free_ (c, ChoiceParticle::free), particle_alloc_ (c, ChoiceParticle::alloc), particle_copy_ (c, ChoiceParticle::copy), - particle_assign_ (c, ChoiceParticle::assign) + particle_assign_ (c, ChoiceParticle::assign), + particle_clone_ (c) { contains_free_ >> particle_free_; contains_alloc_ >> particle_alloc_; contains_copy_ >> particle_copy_; contains_assign_ >> particle_assign_; + contains_clone_ >> particle_clone_; } virtual Void @@ -1499,6 +2242,8 @@ namespace CXX String const& scope (Context::scope (c)); + Boolean fl (fixed_length (c)); + // c-tor () // os << scope << "::" << type << "::" << endl @@ -1517,7 +2262,7 @@ namespace CXX arm_tag << " (" << bad_tag << "));" << "}"; - if (fixed_length (c)) + if (fl) { // copy c-tor // @@ -1586,6 +2331,104 @@ namespace CXX << "}"; Choice::contains (c, contains_func_); + + // _clone + // + if (!fl && clone) + { + // + // _copy + // + String const& arm (earm (c)); + + os << (exceptions ? "void " : "bool ") << scope << "::" << + type << "::" << endl + << "_copy (" << type << "& c) const" + << "{" + << "c." << arm << " (this->" << arm << " ());" + << endl + << "switch (this->" << arm << " ())" + << "{"; + + Choice::contains (c, contains_clone_); + + os << "default:" << endl + << "break;" + << "}"; + + // Copy custom data. + // + if (c.context ().count ("cd-name")) + { + String const& m (ecd_member (c)); + + if (exceptions) + os << "this->" << m << ".copy (c." << m << ");"; + else + os << "if (this->" << m << ".copy (c." << m << "))" << endl + << "return false;" + << endl; + } + + if (!exceptions) + os << "return true;"; + + os << "}"; + + // + // _clone + // + + os << scope << "::" << type << "* " << scope << "::" << + type << "::" << endl + << "_clone () const" + << "{"; + + if (!custom_alloc) + os << type << "* c = new " << type << ";"; + else + os << type << "* c = static_cast< " << type << "* > (" << endl + << "::xsde::cxx::alloc (sizeof (" << type << ")));"; + + if (!exceptions) + os << endl + << "if (c == 0)" << endl + << "return 0;" + << endl; + + if (custom_alloc) + { + if (exceptions) + os << "::xsde::cxx::alloc_guard ag (c);"; + + os << "new (c) " << type << ";"; + + if (exceptions) + os << "ag.release ();"; + } + + if (exceptions) + os << "::xsde::cxx::guard< " << type << " > g (c);" + << "this->_copy (*c);" + << "g.release ();"; + else + { + os << "if (!this->_copy (*c))" + << "{"; + + if (!custom_alloc) + os << "delete c;"; + else + os << "c->~" << type << " ();" + << "::xsde::cxx::free (c);"; + + os << "return 0;" + << "}"; + } + + os << "return c;" + << "}"; + } } Choice::contains (c); @@ -1606,6 +2449,9 @@ namespace CXX ChoiceParticle particle_assign_; Traversal::ContainsParticle contains_assign_; + + ParticleInChoiceClone particle_clone_; + Traversal::ContainsParticle contains_clone_; }; @@ -1617,6 +2463,7 @@ namespace CXX Traversal::ContainsParticle& contains_dtor, Traversal::ContainsParticle& contains_copy, Traversal::ContainsParticle& contains_assign, + Traversal::ContainsParticle& contains_clone, Traversal::ContainsParticle& contains_func) : Context (c), in_choice_ (in_choice), @@ -1624,6 +2471,7 @@ namespace CXX contains_dtor_ (contains_dtor), contains_copy_ (contains_copy), contains_assign_ (contains_assign), + contains_clone_ (contains_clone), contains_func_ (contains_func) { } @@ -1639,6 +2487,8 @@ namespace CXX String const& type (etype (s)); String const& scope (Context::scope (s)); + Boolean fl (fixed_length (s)); + // c-tor () // os << scope << "::" << type << "::" << endl @@ -1659,7 +2509,7 @@ namespace CXX os << "}"; - if (fixed_length (s)) + if (fl) { // copy c-tor // @@ -1686,6 +2536,95 @@ namespace CXX << "}"; } + // _clone + // + if (!fl && clone) + { + // + // _copy + // + + os << (exceptions ? "void " : "bool ") << scope << "::" << + type << "::" << endl + << "_copy (" << type << "& c) const" + << "{"; + + Sequence::contains (s, contains_clone_); + + // Copy custom data. + // + if (s.context ().count ("cd-name")) + { + String const& m (ecd_member (s)); + + if (exceptions) + os << "this->" << m << ".copy (c." << m << ");"; + else + os << "if (this->" << m << ".copy (c." << m << "))" << endl + << "return false;" + << endl; + } + + if (!exceptions) + os << "return true;"; + + os << "}"; + + // + // _clone + // + + os << scope << "::" << type << "* " << scope << "::" << + type << "::" << endl + << "_clone () const" + << "{"; + + if (!custom_alloc) + os << type << "* c = new " << type << ";"; + else + os << type << "* c = static_cast< " << type << "* > (" << endl + << "::xsde::cxx::alloc (sizeof (" << type << ")));"; + + if (!exceptions) + os << endl + << "if (c == 0)" << endl + << "return 0;" + << endl; + + if (custom_alloc) + { + if (exceptions) + os << "::xsde::cxx::alloc_guard ag (c);"; + + os << "new (c) " << type << ";"; + + if (exceptions) + os << "ag.release ();"; + } + + if (exceptions) + os << "::xsde::cxx::guard< " << type << " > g (c);" + << "this->_copy (*c);" + << "g.release ();"; + else + { + os << "if (!this->_copy (*c))" + << "{"; + + if (!custom_alloc) + os << "delete c;"; + else + os << "c->~" << type << " ();" + << "::xsde::cxx::free (c);"; + + os << "return 0;" + << "}"; + } + + os << "return c;" + << "}"; + } + Sequence::contains (s, contains_func_); } @@ -1698,10 +2637,11 @@ namespace CXX Traversal::ContainsParticle& contains_dtor_; Traversal::ContainsParticle& contains_copy_; Traversal::ContainsParticle& contains_assign_; + Traversal::ContainsParticle& contains_clone_; Traversal::ContainsParticle& contains_func_; }; - struct Complex : Traversal::Complex, Context + struct Complex: Traversal::Complex, Context { Complex (Context& c) : Context (c), @@ -1747,13 +2687,22 @@ namespace CXX choice_in_sequence_assign_ (c), sequence_in_sequence_assign_ (c), + // Clone. + // + attribute_clone_ (c), + element_clone_ (c), + all_clone_ (c), + choice_in_sequence_clone_ (c), + sequence_in_sequence_clone_ (c), + // Nested c-tors, etc. // all_ (c, all_contains_ctor_, all_contains_dtor_, all_contains_copy_, - all_contains_assign_), + all_contains_assign_, + all_contains_clone_), choice_in_choice_ (c, true, choice_contains_func_), choice_in_sequence_ (c, false, choice_contains_func_), sequence_in_choice_ ( @@ -1763,6 +2712,7 @@ namespace CXX sequence_contains_dtor_, sequence_contains_copy_, sequence_contains_assign_, + sequence_contains_clone_, sequence_contains_func_), sequence_in_sequence_ ( c, @@ -1771,6 +2721,7 @@ namespace CXX sequence_contains_dtor_, sequence_contains_copy_, sequence_contains_assign_, + sequence_contains_clone_, sequence_contains_func_) { // Functions. @@ -1850,6 +2801,21 @@ namespace CXX contains_compositor_assign_ >> choice_in_sequence_assign_; contains_compositor_assign_ >> sequence_in_sequence_assign_; + // Clone. + // + attribute_names_clone_ >> attribute_clone_; + + all_clone_ >> all_contains_clone_ >> element_clone_; + + sequence_in_sequence_clone_ >> sequence_contains_clone_; + sequence_contains_clone_ >> element_clone_; + sequence_contains_clone_ >> choice_in_sequence_clone_; + sequence_contains_clone_ >> sequence_in_sequence_clone_; + + contains_compositor_clone_ >> all_clone_; + contains_compositor_clone_ >> choice_in_sequence_clone_; + contains_compositor_clone_ >> sequence_in_sequence_clone_; + // Nested c-tors, etc. // all_ >> all_contains_; @@ -1880,6 +2846,7 @@ namespace CXX if (!name) return; + Boolean fl (fixed_length (c)); Boolean poly (polymorphic (c)); Boolean restriction (restriction_p (c)); @@ -1924,7 +2891,7 @@ namespace CXX if (!restriction) { - if (fixed_length (c)) + if (fl) { // copy c-tor // @@ -1980,6 +2947,130 @@ namespace CXX Complex::contains_compositor (c, contains_compositor_func_); } + // _clone + // + if (!fl && clone) + { + // + // _copy + // + + os << (exceptions ? "void " : "bool ") << name << "::" << endl + << "_copy (" << name << "& c) const" + << "{" + << "XSDE_UNUSED (c);" + << endl; + + // Copy the base. + // + if (c.inherits_p ()) + { + SemanticGraph::Type& b (c.inherits ().base ()); + + if (fixed_length (b)) + { + os << "static_cast< "; + base_name_.dispatch (b); + os << "& > (c) = *this;"; + } + else + { + os << "const "; + base_name_.dispatch (b); + os << "& b = *this;"; + + if (exceptions) + os << "b._copy (c);"; + else + os << "if (!b._copy (c))" << endl + << "return false;" + << endl; + } + } + + // Copy members. + // + if (!restriction) + { + Complex::names (c, attribute_names_clone_); + + if (c.contains_compositor_p ()) + Complex::contains_compositor (c, contains_compositor_clone_); + } + + // Copy custom data. + // + if (c.context ().count ("cd-name")) + { + String const& m (ecd_member (c)); + + if (exceptions) + os << "this->" << m << ".copy (c." << m << ");"; + else + os << "if (this->" << m << ".copy (c." << m << "))" << endl + << "return false;" + << endl; + } + + if (!exceptions) + os << "return true;"; + + os << "}"; + + // + // _clone + // + + os << name << "* " << name << "::" << endl + << "_clone () const" + << "{"; + + if (!custom_alloc) + os << name << "* c = new " << name << ";"; + else + os << name << "* c = static_cast< " << name << "* > (" << endl + << "::xsde::cxx::alloc (sizeof (" << name << ")));"; + + if (!exceptions) + os << endl + << "if (c == 0)" << endl + << "return 0;" + << endl; + + if (custom_alloc) + { + if (exceptions) + os << "::xsde::cxx::alloc_guard ag (c);"; + + os << "new (c) " << name << ";"; + + if (exceptions) + os << "ag.release ();"; + } + + if (exceptions) + os << "::xsde::cxx::guard< " << name << " > g (c);" + << "this->_copy (*c);" + << "g.release ();"; + else + { + os << "if (!this->_copy (*c))" + << "{"; + + if (!custom_alloc) + os << "delete c;"; + else + os << "c->~" << name << " ();" + << "::xsde::cxx::free (c);"; + + os << "return 0;" + << "}"; + } + + os << "return c;" + << "}"; + } + if (poly && typeinfo) { String id (c.name ()); @@ -2101,6 +3192,20 @@ namespace CXX Traversal::ContainsCompositor contains_compositor_assign_; + // Clone. + // + AttributeClone attribute_clone_; + Traversal::Names attribute_names_clone_; + + ElementClone element_clone_; + AllClone all_clone_; + ChoiceInSequenceClone choice_in_sequence_clone_; + SequenceInSequenceClone sequence_in_sequence_clone_; + Traversal::ContainsParticle all_contains_clone_; + Traversal::ContainsParticle sequence_contains_clone_; + + Traversal::ContainsCompositor contains_compositor_clone_; + // Nested c-tors, etc. // All all_; @@ -2129,6 +3234,10 @@ namespace CXX ctx.os << "#include " << endl << endl; + if (ctx.clone && ctx.exceptions) + ctx.os << "#include " << endl + << endl; + Traversal::Schema schema; Traversal::Sources sources; Traversal::Names names_ns, names; -- cgit v1.1