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. --- NEWS | 4 + dist/tests/cxx/hybrid/makefile | 2 +- dist/tests/cxx/hybrid/nmakefile | 2 +- documentation/cxx/hybrid/guide/index.xhtml | 38 +- documentation/xsde.1 | 4 + documentation/xsde.xhtml | 5 + libxsde/xsde/cxx/buffer.cxx | 96 +++ libxsde/xsde/cxx/buffer.hxx | 17 + libxsde/xsde/cxx/buffer.ixx | 16 + libxsde/xsde/cxx/guard.hxx | 48 ++ libxsde/xsde/cxx/hybrid/base.hxx | 21 + libxsde/xsde/cxx/hybrid/sequence.cxx | 45 + libxsde/xsde/cxx/hybrid/sequence.hxx | 33 + libxsde/xsde/cxx/hybrid/sequence.ixx | 36 +- libxsde/xsde/cxx/hybrid/sequence.txx | 48 +- libxsde/xsde/cxx/qname.cxx | 118 ++- libxsde/xsde/cxx/qname.hxx | 10 + libxsde/xsde/cxx/qname.ixx | 18 + libxsde/xsde/cxx/string-sequence-stl.cxx | 113 +++ libxsde/xsde/cxx/string-sequence-stl.hxx | 17 + libxsde/xsde/cxx/string-sequence-stl.ixx | 15 +- libxsde/xsde/cxx/string-sequence.cxx | 111 +++ libxsde/xsde/cxx/string-sequence.hxx | 17 + libxsde/xsde/cxx/string-sequence.ixx | 12 + tests/cxx/hybrid/clone/driver.cxx | 79 ++ tests/cxx/hybrid/clone/makefile | 109 +++ tests/cxx/hybrid/clone/test-000.std | 71 ++ tests/cxx/hybrid/clone/test-000.xml | 79 ++ tests/cxx/hybrid/clone/test.xsd | 148 ++++ tests/cxx/hybrid/makefile | 5 +- 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 ++++++++++++++++++++++++++-- 36 files changed, 2762 insertions(+), 145 deletions(-) create mode 100644 libxsde/xsde/cxx/guard.hxx create mode 100644 tests/cxx/hybrid/clone/driver.cxx create mode 100644 tests/cxx/hybrid/clone/makefile create mode 100644 tests/cxx/hybrid/clone/test-000.std create mode 100644 tests/cxx/hybrid/clone/test-000.xml create mode 100644 tests/cxx/hybrid/clone/test.xsd diff --git a/NEWS b/NEWS index 1c4718b..08c82ca 100644 --- a/NEWS +++ b/NEWS @@ -44,6 +44,10 @@ Version 3.2.0 Section 4.3, "Enumerations" in the Getting Started Guide for more information. + * New option, --generate-clone, triggers the generation of clone functions + for variable-length types. These functions allow you to make dynamically- + allocated copies of variable-length objects. + * New configuration parameter, XSDE_STL_ITERATOR, makes iterators provided by the mapping conform to the STL requirements. This feature requires working header and allows you to use the standard diff --git a/dist/tests/cxx/hybrid/makefile b/dist/tests/cxx/hybrid/makefile index ddcf464..7e78d9f 100644 --- a/dist/tests/cxx/hybrid/makefile +++ b/dist/tests/cxx/hybrid/makefile @@ -30,7 +30,7 @@ dirs += binary/xdr endif ifeq ($(XSDE_PARSER_VALIDATION),y) -dirs += choice recursive +dirs += choice recursive clone endif endif # XSDE_IOSTREAM diff --git a/dist/tests/cxx/hybrid/nmakefile b/dist/tests/cxx/hybrid/nmakefile index 1127649..b31619b 100644 --- a/dist/tests/cxx/hybrid/nmakefile +++ b/dist/tests/cxx/hybrid/nmakefile @@ -30,7 +30,7 @@ dirs = $(dirs) binary/xdr !endif !if "$(XSDE_PARSER_VALIDATION)" == "y" -dirs = $(dirs) choice recursive +dirs = $(dirs) choice recursive clone !endif !endif # XSDE_IOSTREAM diff --git a/documentation/cxx/hybrid/guide/index.xhtml b/documentation/cxx/hybrid/guide/index.xhtml index 39d7e9b..7d33a4e 100644 --- a/documentation/cxx/hybrid/guide/index.xhtml +++ b/documentation/cxx/hybrid/guide/index.xhtml @@ -2024,10 +2024,21 @@ private: (see Section 3.8, "Custom Allocators"), the object model expects you to allocate such an object with operator new and will eventually delete it - with operator delete. You can also request generation - of detach functions with the --generate-detach compiler - option. These functions allow you to detach a variable-length - object from the object model. As an example, let us extend + with operator delete.

+ +

If you wish to make copies of variable-length objects, then + you can request the generation of the object cloning functions + with the --generate-clone compiler + option. When this option is specified, each variable-length + type implements the _clone() function which returns + a dynamically-allocated copy of the object or NULL + if the allocation failed and C++ exceptions are disabled (see + Section 3.3, "C++ Exceptions").

+ +

You can also request generation of detach functions with the + --generate-detach compiler option. These functions + allow you to detach a variable-length object from the object model. + As an example, let us extend our people.xsd schema with the following type:

@@ -2039,8 +2050,9 @@ private:
 </xs:complexType>
   
-

If we compile it with XSD/e and specify the --generate-detach - option, we will get the following C++ class:

+

If we compile it with XSD/e and specify the + --generate-clone and --generate-detach + options, we will get the following C++ class:

 // staff (variable-length)
@@ -2050,6 +2062,9 @@ class staff
 public:
   staff ();
 
+  staff*
+  _clone () const;
+
 private:
   staff (const staff&);
   staff& operator= (const staff&);
@@ -4143,7 +4158,9 @@ for (people::person_iterator i = ps.begin (); i != ps.end (); ++i)
      type is always variable-length which means objects of polymorphic
      types are allocated dynamically and are stored and passed around
      as pointers or references. A polymorphic type also defines a
-     virtual destructor which allows you to delete an instance of a
+     virtual _clone() function (see Section 4.2,
+     "Memory Management") and a virtual destructor
+     which allow you to copy and delete an instance of a
      polymorphic type via a pointer to its base. The following code
      fragment shows how we can parse, access, modify, and serialize
      the above XML document:

@@ -4957,11 +4974,15 @@ namespace xml_schema public: void + assign (void* data, size_t size); + + void attach (void* data, size_t size, size_t capacity); void* detach (); + void swap (buffer&); @@ -5048,6 +5069,9 @@ namespace xml_schema public: error + assign (void* data, size_t size); + + error attach (void* data, size_t size, size_t capacity); void* diff --git a/documentation/xsde.1 b/documentation/xsde.1 index a4b55dc..4257882 100644 --- a/documentation/xsde.1 +++ b/documentation/xsde.1 @@ -1006,6 +1006,10 @@ documents. .IP "\fB\--suppress-enum\fR" Suppress the generation of the XML Schema enumeration to C++ enum mapping. +.IP "\fB\--generate-clone\fR" +Generate clone functions for variable-length types. These functions allow +you to make dynamically-allocated copies of variable-length objects. + .IP "\fB\--generate-detach\fR" Generate detach functions for elements and attributes of variable-length types. These functions, for example, allow you to move sub-trees in the diff --git a/documentation/xsde.xhtml b/documentation/xsde.xhtml index 859719e..9797ba9 100644 --- a/documentation/xsde.xhtml +++ b/documentation/xsde.xhtml @@ -870,6 +870,11 @@
Suppress the generation of the XML Schema enumeration to C++ enum mapping.
+
--generate-clone
+
Generate clone functions for variable-length types. These + functions allow you to make dynamically-allocated copies of + variable-length objects.
+
--generate-detach
Generate detach functions for elements and attributes of variable-length types. These functions, for example, allow diff --git a/libxsde/xsde/cxx/buffer.cxx b/libxsde/xsde/cxx/buffer.cxx index d9102ae..4084cde 100644 --- a/libxsde/xsde/cxx/buffer.cxx +++ b/libxsde/xsde/cxx/buffer.cxx @@ -110,6 +110,58 @@ namespace xsde return true; } } + + void buffer:: + assign (void* data, size_t size) + { + capacity (size); + size_ = size; + + if (size_) + memcpy (data_, data, size_); + } + + struct buffer_guard + { + buffer_guard (buffer* p) : p_ (p) {} + + ~buffer_guard () + { +#ifndef XSDE_CUSTOM_ALLOCATOR + delete p_; +#else + if (p_ != 0) + { + p_->~buffer (); + cxx::free (p_); + } +#endif + } + + void + release () { p_ = 0; } + + private: + buffer* p_; + }; + + buffer* buffer:: + _clone () const + { +#ifndef XSDE_CUSTOM_ALLOCATOR + buffer* c = new buffer; +#else + // Default buffer c-tor cannot throw so we don't need alloc_guard. + // + buffer* c = static_cast (cxx::alloc (sizeof (buffer))); + new (c) buffer; +#endif + buffer_guard g (c); + _copy (*c); + g.release (); + return c; + } + #else buffer::error buffer:: capacity (size_t capacity, bool copy, bool* moved) @@ -156,6 +208,50 @@ namespace xsde return error_none; } + + buffer::error buffer:: + assign (void* data, size_t size) + { + if (error r = capacity (size)) + return r; + + size_ = size; + + if (size_) + memcpy (data_, data, size_); + + return error_none; + } + + buffer* buffer:: + _clone () const + { +#ifndef XSDE_CUSTOM_ALLOCATOR + buffer* c = new buffer; +#else + buffer* c = static_cast (cxx::alloc (sizeof (buffer))); +#endif + + if (c == 0) + return 0; + +#ifdef XSDE_CUSTOM_ALLOCATOR + new (c) buffer; +#endif + + if (!_copy (*c)) + { +#ifndef XSDE_CUSTOM_ALLOCATOR + delete c; +#else + c->~buffer (); + cxx::free (c); +#endif + return 0; + } + + return c; + } #endif } } diff --git a/libxsde/xsde/cxx/buffer.hxx b/libxsde/xsde/cxx/buffer.hxx index 7ea1adf..2957a0a 100644 --- a/libxsde/xsde/cxx/buffer.hxx +++ b/libxsde/xsde/cxx/buffer.hxx @@ -60,6 +60,13 @@ namespace xsde #else void #endif + assign (void* data, size_t size); + +#ifndef XSDE_EXCEPTIONS + error +#else + void +#endif attach (void* data, size_t size, size_t capacity); void* @@ -68,6 +75,16 @@ namespace xsde void swap (buffer&); + buffer* + _clone () const; + +#ifndef XSDE_EXCEPTIONS + bool +#else + void +#endif + _copy (buffer&) const; + public: size_t capacity () const; diff --git a/libxsde/xsde/cxx/buffer.ixx b/libxsde/xsde/cxx/buffer.ixx index 2229396..d9c71eb 100644 --- a/libxsde/xsde/cxx/buffer.ixx +++ b/libxsde/xsde/cxx/buffer.ixx @@ -220,5 +220,21 @@ namespace xsde { return !(x == y); } + + // + // +#ifndef XSDE_EXCEPTIONS + inline bool buffer:: + _copy (buffer& c) const + { + return c.assign (data_, size_) == error_none; + } +#else + inline void buffer:: + _copy (buffer& c) const + { + c.assign (data_, size_); + } +#endif } } diff --git a/libxsde/xsde/cxx/guard.hxx b/libxsde/xsde/cxx/guard.hxx new file mode 100644 index 0000000..3190983 --- /dev/null +++ b/libxsde/xsde/cxx/guard.hxx @@ -0,0 +1,48 @@ +// file : xsde/cxx/guard.hxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2010 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#ifndef XSDE_CXX_GUARD_HXX +#define XSDE_CXX_GUARD_HXX + +#include + +#ifdef XSDE_CUSTOM_ALLOCATOR +# include +#endif + +namespace xsde +{ + namespace cxx + { +#ifdef XSDE_EXCEPTIONS + template + struct guard + { + guard (T* p) : p_ (p) {} + + ~guard () + { +#ifndef XSDE_CUSTOM_ALLOCATOR + delete p_; +#else + if (p_ != 0) + { + p_->~T (); + cxx::free (p_); + } +#endif + } + + void + release () { p_ = 0; } + + private: + T* p_; + }; +#endif // XSDE_EXCEPTIONS + } +} + +#endif // XSDE_CXX_GUARD_HXX diff --git a/libxsde/xsde/cxx/hybrid/base.hxx b/libxsde/xsde/cxx/hybrid/base.hxx index 89431a2..a7b1e2a 100644 --- a/libxsde/xsde/cxx/hybrid/base.hxx +++ b/libxsde/xsde/cxx/hybrid/base.hxx @@ -10,6 +10,7 @@ #ifndef XSDE_STL # include // strcmp +# include #endif #ifdef XSDE_CUSTOM_ALLOCATOR @@ -599,6 +600,26 @@ namespace xsde string_base& operator= (char* x) {base_value (x); return *this;} +#ifndef XSDE_EXCEPTIONS + bool +#else + void +#endif + _copy (string_base& c) const + { + char* x = strdupx (x_); + +#ifndef XSDE_EXCEPTIONS + if (x == 0) + return false; +#endif + c.base_value (x); + +#ifndef XSDE_EXCEPTIONS + return true; +#endif + } + protected: char* x_; }; diff --git a/libxsde/xsde/cxx/hybrid/sequence.cxx b/libxsde/xsde/cxx/hybrid/sequence.cxx index bf5f3c7..5293616 100644 --- a/libxsde/xsde/cxx/hybrid/sequence.cxx +++ b/libxsde/xsde/cxx/hybrid/sequence.cxx @@ -26,6 +26,51 @@ namespace xsde size_ = 0; } + +#ifdef XSDE_EXCEPTIONS + void data_sequence:: + copy (data_sequence& c) const + { + if (c.size_ != 0) + c.clear (); + + c.destructor_ = destructor_; + c.clone_ = clone_; + + c.reserve (size_); + + for (; c.size_ < size_; ++c.size_) + { + static_cast (c.data_)[c.size_] = + clone_ (static_cast (data_)[c.size_], c.size_); + } + } +#else + sequence_base::error data_sequence:: + copy (data_sequence& c) const + { + if (c.size_ != 0) + c.clear (); + + c.destructor_ = destructor_; + c.clone_ = clone_; + + if (error r = c.reserve (size_)) + return r; + + for (; c.size_ < size_; ++c.size_) + { + void* x = clone_ (static_cast (data_)[c.size_], c.size_); + + if (x == 0) + return error_no_memory; + + static_cast (c.data_)[c.size_] = x; + } + + return error_none; + } +#endif } } } diff --git a/libxsde/xsde/cxx/hybrid/sequence.hxx b/libxsde/xsde/cxx/hybrid/sequence.hxx index fa5c697..e21f219 100644 --- a/libxsde/xsde/cxx/hybrid/sequence.hxx +++ b/libxsde/xsde/cxx/hybrid/sequence.hxx @@ -128,6 +128,13 @@ namespace xsde void swap (pod_sequence&); + +#ifndef XSDE_EXCEPTIONS + error +#else + void +#endif + copy (pod_sequence&) const; }; // Sequence with fixed-length elements. @@ -230,6 +237,13 @@ namespace xsde void swap (fix_sequence&); +#ifndef XSDE_EXCEPTIONS + error +#else + void +#endif + copy (fix_sequence&) const; + private: static void move_ (void* dst, void* src, size_t n); @@ -831,6 +845,13 @@ namespace xsde void swap (var_sequence&); +#ifndef XSDE_EXCEPTIONS + error +#else + void +#endif + copy (var_sequence&) const; + #ifdef XSDE_EXCEPTIONS public: struct guard @@ -877,10 +898,14 @@ namespace xsde data_sequence (); typedef void (*destroy_func) (void* data, size_t pos); + typedef void* (*clone_func) (void* data, size_t pos); void destructor (destroy_func); + void + clone (clone_func); + public: iterator begin (); @@ -953,8 +978,16 @@ namespace xsde void swap (data_sequence&); +#ifndef XSDE_EXCEPTIONS + error +#else + void +#endif + copy (data_sequence&) const; + private: destroy_func destructor_; + clone_func clone_; }; } } diff --git a/libxsde/xsde/cxx/hybrid/sequence.ixx b/libxsde/xsde/cxx/hybrid/sequence.ixx index 1ec2a4c..e53b774 100644 --- a/libxsde/xsde/cxx/hybrid/sequence.ixx +++ b/libxsde/xsde/cxx/hybrid/sequence.ixx @@ -167,6 +167,13 @@ namespace xsde memcpy (data_, p, n * sizeof (T)); size_ = n; } + + template + inline void pod_sequence:: + copy (pod_sequence& c) const + { + c.assign (begin (), size ()); + } #else template inline sequence_base::error pod_sequence:: @@ -238,6 +245,13 @@ namespace xsde size_ = n; return error_none; } + + template + inline sequence_base::error pod_sequence:: + copy (pod_sequence& c) const + { + return c.assign (begin (), size ()); + } #endif // @@ -387,6 +401,13 @@ namespace xsde if (capacity_ < n) grow_ (n, sizeof (T), &move_); } + + template + inline void fix_sequence:: + copy (fix_sequence& c) const + { + c.assign (begin (), size ()); + } #else template inline sequence_base::error fix_sequence:: @@ -448,6 +469,13 @@ namespace xsde r = grow_ (n, sizeof (T), &move_); return r; } + + template + inline sequence_base::error fix_sequence:: + copy (fix_sequence& c) const + { + return c.assign (begin (), size ()); + } #endif // @@ -741,7 +769,7 @@ namespace xsde inline data_sequence:: data_sequence () - : destructor_ (0) + : destructor_ (0), clone_ (0) { } @@ -751,6 +779,12 @@ namespace xsde destructor_ = d; } + inline void data_sequence:: + clone (data_sequence::clone_func c) + { + clone_ = c; + } + inline size_t data_sequence:: max_size () const { diff --git a/libxsde/xsde/cxx/hybrid/sequence.txx b/libxsde/xsde/cxx/hybrid/sequence.txx index b79e9d5..5d7df7d 100644 --- a/libxsde/xsde/cxx/hybrid/sequence.txx +++ b/libxsde/xsde/cxx/hybrid/sequence.txx @@ -30,7 +30,9 @@ namespace xsde void fix_sequence:: assign (const T* p, size_t n) { - clear (); + if (size_ != 0) + clear (); + reserve (n); for (; size_ < n; ++size_) @@ -41,7 +43,8 @@ namespace xsde sequence_base::error fix_sequence:: assign (const T* p, size_t n) { - clear (); + if (size_ != 0) + clear (); if (error r = reserve (n)) return r; @@ -166,6 +169,47 @@ namespace xsde size_ = 0; } + +#ifdef XSDE_EXCEPTIONS + template + void var_sequence:: + copy (var_sequence& c) const + { + if (c.size_ != 0) + c.clear (); + + c.reserve (size_); + + for (; c.size_ < size_; ++c.size_) + { + static_cast (c.data_)[c.size_] = + static_cast (data_)[c.size_]->_clone (); + } + } +#else + template + sequence_base::error var_sequence:: + copy (var_sequence& c) const + { + if (c.size_ != 0) + c.clear (); + + if (error r = c.reserve (size_)) + return r; + + for (; c.size_ < size_; ++c.size_) + { + T* x = static_cast (data_)[c.size_]->_clone (); + + if (x == 0) + return error_no_memory; + + static_cast (c.data_)[c.size_] = x; + } + + return error_none; + } +#endif } } } diff --git a/libxsde/xsde/cxx/qname.cxx b/libxsde/xsde/cxx/qname.cxx index be196be..f1e4238 100644 --- a/libxsde/xsde/cxx/qname.cxx +++ b/libxsde/xsde/cxx/qname.cxx @@ -10,11 +10,83 @@ namespace xsde { namespace cxx { -#ifndef XSDE_EXCEPTIONS - qname::error qname:: + +#ifdef XSDE_EXCEPTIONS + + void qname:: + prefix_copy (const char* prefix) + { +#ifndef XSDE_CUSTOM_ALLOCATOR + delete[] prefix_; #else + cxx::free (prefix_); +#endif + + if (prefix) + prefix_ = strdupx (prefix); + else + prefix_ = 0; + } + void qname:: + name_copy (const char* name) + { +#ifndef XSDE_CUSTOM_ALLOCATOR + delete[] name_; +#else + cxx::free (name_); +#endif + + if (name) + name_ = strdupx (name); + else + name_ = 0; + } + + struct qname_guard + { + qname_guard (qname* p) : p_ (p) {} + + ~qname_guard () + { +#ifndef XSDE_CUSTOM_ALLOCATOR + delete p_; +#else + if (p_ != 0) + { + p_->~qname (); + cxx::free (p_); + } #endif + } + + void + release () { p_ = 0; } + + private: + qname* p_; + }; + + qname* qname:: + _clone () const + { +#ifndef XSDE_CUSTOM_ALLOCATOR + qname* c = new qname; +#else + // Default qname c-tor cannot throw so we don't need alloc_guard. + // + qname* c = static_cast (cxx::alloc (sizeof (qname))); + new (c) qname; +#endif + qname_guard g (c); + _copy (*c); + g.release (); + return c; + } + +#else + + qname::error qname:: prefix_copy (const char* prefix) { #ifndef XSDE_CUSTOM_ALLOCATOR @@ -27,24 +99,16 @@ namespace xsde { prefix_ = strdupx (prefix); -#ifndef XSDE_EXCEPTIONS if (prefix_ == 0) return error_no_memory; -#endif } else prefix_ = 0; -#ifndef XSDE_EXCEPTIONS return error_none; -#endif } -#ifndef XSDE_EXCEPTIONS qname::error qname:: -#else - void qname:: -#endif name_copy (const char* name) { #ifndef XSDE_CUSTOM_ALLOCATOR @@ -57,17 +121,45 @@ namespace xsde { name_ = strdupx (name); -#ifndef XSDE_EXCEPTIONS if (name_ == 0) return error_no_memory; -#endif } else name_ = 0; -#ifndef XSDE_EXCEPTIONS return error_none; + } + + qname* qname:: + _clone () const + { +#ifndef XSDE_CUSTOM_ALLOCATOR + qname* c = new qname; +#else + qname* c = static_cast (cxx::alloc (sizeof (qname))); +#endif + + if (c == 0) + return 0; + +#ifdef XSDE_CUSTOM_ALLOCATOR + new (c) qname; #endif + + if (!_copy (*c)) + { +#ifndef XSDE_CUSTOM_ALLOCATOR + delete c; +#else + c->~qname (); + cxx::free (c); +#endif + return 0; + } + + return c; } + +#endif } } diff --git a/libxsde/xsde/cxx/qname.hxx b/libxsde/xsde/cxx/qname.hxx index 0b2d5f5..85b53bd 100644 --- a/libxsde/xsde/cxx/qname.hxx +++ b/libxsde/xsde/cxx/qname.hxx @@ -81,6 +81,16 @@ namespace xsde char* name_detach (); + qname* + _clone () const; + +#ifndef XSDE_EXCEPTIONS + bool +#else + void +#endif + _copy (qname&) const; + private: char* prefix_; char* name_; diff --git a/libxsde/xsde/cxx/qname.ixx b/libxsde/xsde/cxx/qname.ixx index f449ef3..7a374c6 100644 --- a/libxsde/xsde/cxx/qname.ixx +++ b/libxsde/xsde/cxx/qname.ixx @@ -124,6 +124,24 @@ namespace xsde return r; } +#ifdef XSDE_EXCEPTIONS + inline void qname:: + _copy (qname& c) const + { + c.prefix_copy (prefix_); + c.name_copy (name_); + } +#else + inline bool qname:: + _copy (qname& c) const + { + if (c.prefix_copy (prefix_) || c.name_copy (name_)) + return false; + + return true; + } +#endif + // // inline bool diff --git a/libxsde/xsde/cxx/string-sequence-stl.cxx b/libxsde/xsde/cxx/string-sequence-stl.cxx index 255b341..2fd8a02 100644 --- a/libxsde/xsde/cxx/string-sequence-stl.cxx +++ b/libxsde/xsde/cxx/string-sequence-stl.cxx @@ -5,6 +5,10 @@ #include +#ifdef XSDE_CUSTOM_ALLOCATOR +# include +#endif + namespace xsde { namespace cxx @@ -20,6 +24,115 @@ namespace xsde } #ifdef XSDE_EXCEPTIONS + void string_sequence:: + copy (string_sequence& c) const + { + if (c.size_ != 0) + c.clear (); + + c.reserve (size_); + + for (; c.size_ < size_; ++c.size_) + { + new (static_cast (c.data_) + c.size_) std::string ( + static_cast (data_)[c.size_]); + } + } + + struct string_sequence_guard + { + string_sequence_guard (string_sequence* p) : p_ (p) {} + + ~string_sequence_guard () + { +#ifndef XSDE_CUSTOM_ALLOCATOR + delete p_; +#else + if (p_ != 0) + { + p_->~string_sequence (); + cxx::free (p_); + } +#endif + } + + void + release () { p_ = 0; } + + private: + string_sequence* p_; + }; + + string_sequence* string_sequence:: + _clone () const + { +#ifndef XSDE_CUSTOM_ALLOCATOR + string_sequence* c = new string_sequence; +#else + // Default string_sequence c-tor cannot throw so we don't need + // alloc_guard. + // + string_sequence* c = static_cast ( + cxx::alloc (sizeof (string_sequence))); + new (c) string_sequence; +#endif + string_sequence_guard g (c); + _copy (*c); + g.release (); + return c; + } +#else + sequence_base::error string_sequence:: + copy (string_sequence& c) const + { + if (c.size_ != 0) + c.clear (); + + if (error r = c.reserve (size_)) + return r; + + for (; c.size_ < size_; ++c.size_) + { + new (static_cast (c.data_) + c.size_) std::string ( + static_cast (data_)[c.size_]); + } + + return error_none; + } + + string_sequence* string_sequence:: + _clone () const + { +#ifndef XSDE_CUSTOM_ALLOCATOR + string_sequence* c = new string_sequence; +#else + string_sequence* c = static_cast ( + cxx::alloc (sizeof (string_sequence))); +#endif + + if (c == 0) + return 0; + +#ifdef XSDE_CUSTOM_ALLOCATOR + new (c) string_sequence; +#endif + + if (!_copy (*c)) + { +#ifndef XSDE_CUSTOM_ALLOCATOR + delete c; +#else + c->~string_sequence (); + cxx::free (c); +#endif + return 0; + } + + return c; + } +#endif + +#ifdef XSDE_EXCEPTIONS struct guard { guard (std::string* p, size_t& n) : p_ (p), n_ (n) {} diff --git a/libxsde/xsde/cxx/string-sequence-stl.hxx b/libxsde/xsde/cxx/string-sequence-stl.hxx index 305fd0d..5e75ad8 100644 --- a/libxsde/xsde/cxx/string-sequence-stl.hxx +++ b/libxsde/xsde/cxx/string-sequence-stl.hxx @@ -106,6 +106,23 @@ namespace xsde void swap (string_sequence&); +#ifndef XSDE_EXCEPTIONS + error +#else + void +#endif + copy (string_sequence&) const; + + string_sequence* + _clone () const; + +#ifndef XSDE_EXCEPTIONS + bool +#else + void +#endif + _copy (string_sequence&) const; + private: static void move_ (void* dst, void* src, size_t n); diff --git a/libxsde/xsde/cxx/string-sequence-stl.ixx b/libxsde/xsde/cxx/string-sequence-stl.ixx index 55e3d5d..ae09d04 100644 --- a/libxsde/xsde/cxx/string-sequence-stl.ixx +++ b/libxsde/xsde/cxx/string-sequence-stl.ixx @@ -134,8 +134,15 @@ namespace xsde reserve (size_t n) { if (capacity_ < n) - grow_ (n, sizeof (std::string*), &move_); + grow_ (n, sizeof (std::string), &move_); } + + inline void string_sequence:: + _copy (string_sequence& c) const + { + copy (c); + } + #else inline sequence_base::error string_sequence:: push_back (const std::string& x) @@ -193,6 +200,12 @@ namespace xsde r = grow_ (n, sizeof (std::string), &move_); return r; } + + inline bool string_sequence:: + _copy (string_sequence& c) const + { + return copy (c) == error_none; + } #endif inline bool diff --git a/libxsde/xsde/cxx/string-sequence.cxx b/libxsde/xsde/cxx/string-sequence.cxx index 5387e79..63944fb 100644 --- a/libxsde/xsde/cxx/string-sequence.cxx +++ b/libxsde/xsde/cxx/string-sequence.cxx @@ -34,6 +34,64 @@ namespace xsde static_cast (data_)[size_++] = strdupx (cs); } + + void string_sequence:: + copy (string_sequence& c) const + { + if (c.size_ != 0) + c.clear (); + + c.reserve (size_); + + for (; c.size_ < size_; ++c.size_) + { + static_cast (c.data_)[c.size_] = + strdupx (static_cast (data_)[c.size_]); + } + } + + struct string_sequence_guard + { + string_sequence_guard (string_sequence* p) : p_ (p) {} + + ~string_sequence_guard () + { +#ifndef XSDE_CUSTOM_ALLOCATOR + delete p_; +#else + if (p_ != 0) + { + p_->~string_sequence (); + cxx::free (p_); + } +#endif + } + + void + release () { p_ = 0; } + + private: + string_sequence* p_; + }; + + string_sequence* string_sequence:: + _clone () const + { +#ifndef XSDE_CUSTOM_ALLOCATOR + string_sequence* c = new string_sequence; +#else + // Default string_sequence c-tor cannot throw so we don't need + // alloc_guard. + // + string_sequence* c = static_cast ( + cxx::alloc (sizeof (string_sequence))); + new (c) string_sequence; +#endif + string_sequence_guard g (c); + _copy (*c); + g.release (); + return c; + } #else string_sequence::error string_sequence:: push_back_copy (const char* cs) @@ -55,6 +113,59 @@ namespace xsde return r; } + + sequence_base::error string_sequence:: + copy (string_sequence& c) const + { + if (c.size_ != 0) + c.clear (); + + if (error r = c.reserve (size_)) + return r; + + for (; c.size_ < size_; ++c.size_) + { + char* x = strdupx (static_cast (data_)[c.size_]); + + if (x == 0) + return error_no_memory; + + static_cast (c.data_)[c.size_] = x; + } + + return error_none; + } + + string_sequence* string_sequence:: + _clone () const + { +#ifndef XSDE_CUSTOM_ALLOCATOR + string_sequence* c = new string_sequence; +#else + string_sequence* c = static_cast ( + cxx::alloc (sizeof (string_sequence))); +#endif + + if (c == 0) + return 0; + +#ifdef XSDE_CUSTOM_ALLOCATOR + new (c) string_sequence; +#endif + + if (!_copy (*c)) + { +#ifndef XSDE_CUSTOM_ALLOCATOR + delete c; +#else + c->~string_sequence (); + cxx::free (c); +#endif + return 0; + } + + return c; + } #endif bool diff --git a/libxsde/xsde/cxx/string-sequence.hxx b/libxsde/xsde/cxx/string-sequence.hxx index c9a33e4..a94418a 100644 --- a/libxsde/xsde/cxx/string-sequence.hxx +++ b/libxsde/xsde/cxx/string-sequence.hxx @@ -123,6 +123,23 @@ namespace xsde void swap (string_sequence&); + +#ifndef XSDE_EXCEPTIONS + error +#else + void +#endif + copy (string_sequence&) const; + + string_sequence* + _clone () const; + +#ifndef XSDE_EXCEPTIONS + bool +#else + void +#endif + _copy (string_sequence&) const; }; bool diff --git a/libxsde/xsde/cxx/string-sequence.ixx b/libxsde/xsde/cxx/string-sequence.ixx index b902bd7..b74adf2 100644 --- a/libxsde/xsde/cxx/string-sequence.ixx +++ b/libxsde/xsde/cxx/string-sequence.ixx @@ -172,6 +172,12 @@ namespace xsde if (capacity_ < n) grow_ (n, sizeof (char*), 0); } + + inline void string_sequence:: + _copy (string_sequence& c) const + { + copy (c); + } #else inline sequence_base::error string_sequence:: push_back (char* x) @@ -244,6 +250,12 @@ namespace xsde r = grow_ (n, sizeof (char*), 0); return r; } + + inline bool string_sequence:: + _copy (string_sequence& c) const + { + return copy (c) == error_none; + } #endif inline char* string_sequence:: diff --git a/tests/cxx/hybrid/clone/driver.cxx b/tests/cxx/hybrid/clone/driver.cxx new file mode 100644 index 0000000..5d044ca --- /dev/null +++ b/tests/cxx/hybrid/clone/driver.cxx @@ -0,0 +1,79 @@ +// file : tests/cxx/hybrid/clone/driver.cxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2006-2010 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +// Test _clone() functionality. +// + +#include +#include + +#include "test.hxx" +#include "test-pimpl.hxx" +#include "test-simpl.hxx" + +using namespace std; +using namespace test; + +void +data_destructor (void* p, size_t) +{ + delete static_cast (p); +} + +void* +data_clone (void* p, size_t) +{ + return new int (*static_cast (p)); +} + +int +main (int argc, char* argv[]) +{ + if (argc != 2) + { + cerr << "usage: " << argv[0] << " test.xml" << endl; + return 1; + } + + // Parse. + // + root_paggr root_p; + + xml_schema::document_pimpl doc_p ( + root_p.root_parser (), + root_p.root_namespace (), + root_p.root_name ()); + + root_p.pre (); + doc_p.parse (argv[1]); + type* r = root_p.post (); + + r->complex ().custom_data ().destructor (&data_destructor); + r->complex ().custom_data ().clone (&data_clone); + r->complex ().custom_data ().push_back (new int (123)); + + type* c = r->_clone (); + delete r; + + assert (c->complex ().custom_data ().size () == 1); + assert (*static_cast (c->complex ().custom_data ()[0]) == 123); + + // Serialize. + // + root_saggr root_s; + + xml_schema::document_simpl doc_s ( + root_s.root_serializer (), + root_s.root_namespace (), + root_s.root_name ()); + + doc_s.add_prefix ("t", "test"); + + root_s.pre (*c); + doc_s.serialize (cout, xml_schema::document_simpl::pretty_print); + root_s.post (); + + delete c; +} diff --git a/tests/cxx/hybrid/clone/makefile b/tests/cxx/hybrid/clone/makefile new file mode 100644 index 0000000..7138869 --- /dev/null +++ b/tests/cxx/hybrid/clone/makefile @@ -0,0 +1,109 @@ +# file : tests/cxx/hybrid/clone/makefile +# author : Boris Kolpackov +# copyright : Copyright (c) 2006-2010 Code Synthesis Tools CC +# license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +include $(dir $(lastword $(MAKEFILE_LIST)))../../../../build/bootstrap.make + +xsd := test.xsd +cxx := driver.cxx + +obj := $(addprefix $(out_base)/,\ +$(cxx:.cxx=.o) \ +$(xsd:.xsd=.o) \ +$(xsd:.xsd=-pskel.o) \ +$(xsd:.xsd=-pimpl.o) \ +$(xsd:.xsd=-sskel.o) \ +$(xsd:.xsd=-simpl.o)) + +dep := $(obj:.o=.o.d) + +xsde.l := $(out_root)/libxsde/xsde/xsde.l +xsde.l.cpp-options := $(out_root)/libxsde/xsde/xsde.l.cpp-options + +driver := $(out_base)/driver +test := $(out_base)/.test +dist := $(out_base)/.dist +dist-win := $(out_base)/.dist-win +clean := $(out_base)/.clean + + +# Build. +# +$(driver): $(obj) $(xsde.l) + +$(obj) $(dep): $(xsde.l.cpp-options) + +genf := $(xsd:.xsd=.hxx) $(xsd:.xsd=.cxx) \ + $(xsd:.xsd=-pskel.hxx) $(xsd:.xsd=-pskel.cxx) \ + $(xsd:.xsd=-pimpl.hxx) $(xsd:.xsd=-pimpl.cxx) \ + $(xsd:.xsd=-sskel.hxx) $(xsd:.xsd=-sskel.cxx) \ + $(xsd:.xsd=-simpl.hxx) $(xsd:.xsd=-simpl.cxx) + +gen := $(addprefix $(out_base)/,$(genf)) + +$(gen): $(out_root)/xsde/xsde +$(gen): xsde := $(out_root)/xsde/xsde +$(gen) $(dist) $(dist-win): xsde_options += --generate-parser \ +--generate-serializer --generate-aggregate --generate-clone \ +--custom-data complex + +$(call include-dep,$(dep)) + +# Convenience alias for default target. +# +$(out_base)/: $(driver) + + +# Test. +# +$(test): driver := $(driver) +$(test): $(driver) $(src_base)/test-000.xml $(src_base)/test-000.std + $(call message,test $$1,$$1 $(src_base)/test-000.xml | diff -u $(src_base)/test-000.std -,$(driver)) + + +# Dist. +# +$(dist) $(dist-win): opt := -src $(src_base) -cmd cxx-hybrid -xsd "$(xsd)" \ +-cxx "$(cxx)" -gen "$(genf)" -opt "$(xsde_options)" -out $(dist_prefix) + +$(dist): + $(call message,install $(src_base),$(scf_root)/dist $(opt)) + +$(dist-win): + $(call message,install $(src_base),$(scf_root)/dist -win $(opt)) + + +# Clean. +# +$(clean): $(driver).o.clean \ + $(addsuffix .cxx.clean,$(obj)) \ + $(addsuffix .cxx.clean,$(dep)) \ + $(addprefix $(out_base)/,$(xsd:.xsd=.cxx.xsd.clean)) + + +# Generated .gitignore. +# +ifeq ($(out_base),$(src_base)) +$(gen): | $(out_base)/.gitignore +$(driver): | $(out_base)/.gitignore + +$(out_base)/.gitignore: files := driver $(genf) +$(clean): $(out_base)/.gitignore.clean + +$(call include,$(bld_root)/git/gitignore.make) +endif + + +# How to. +# +$(call include,$(bld_root)/cxx/o-e.make) +$(call include,$(bld_root)/cxx/cxx-o.make) +$(call include,$(bld_root)/cxx/cxx-d.make) +$(call include,$(scf_root)/xsde/hybrid/xsd-cxx.make) + + +# Dependencies. +# +$(call import,$(src_root)/xsde/makefile) +$(call import,$(src_root)/libxsde/xsde/makefile) diff --git a/tests/cxx/hybrid/clone/test-000.std b/tests/cxx/hybrid/clone/test-000.std new file mode 100644 index 0000000..f50ea2f --- /dev/null +++ b/tests/cxx/hybrid/clone/test-000.std @@ -0,0 +1,71 @@ + + + 123 + abc def ghq + 123 + abc def ghq + 1 + 2 + 3 + + 1 + 1 + + + 2 + 2 + + + 3 + 3 + + a1 b1 c1 + a2 b2 c2 + a3 b3 c3 + aaa + bbb + ccc + abc def ghq + + + 123 + abc def ghq + 123 + abc def ghq + + + 123 + abc def ghq + 123 + abc def ghq + abc def ghq + 123 + + + 123 + + + abc def ghq + + + 123 + abc def ghq + 123 + abc def ghq + + + 1 + 1 + abc def ghq + + + 1 + abc def ghq + 123 + + str str + abc def ghq + abc + c + b + \ No newline at end of file diff --git a/tests/cxx/hybrid/clone/test-000.xml b/tests/cxx/hybrid/clone/test-000.xml new file mode 100644 index 0000000..c10c1b7 --- /dev/null +++ b/tests/cxx/hybrid/clone/test-000.xml @@ -0,0 +1,79 @@ + + + 123 + abc def ghq + 123 + abc def ghq + + 1 + 2 + 3 + + 11 + 22 + 33 + + a1 b1 c1 + a2 b2 c2 + a3 b3 c3 + + aaa + bbb + ccc + + abc def ghq + + + + 123 + abc def ghq + 123 + abc def ghq + + + + 123 + abc def ghq + 123 + abc def ghq + + abc def ghq + + 123 + + + + 123 + + + + abc def ghq + + + + 123 + abc def ghq + 123 + abc def ghq + + + + 1 + 1 + abc def ghq + + + + 1 + abc def ghq + 123 + + + str str + + abc def ghq + abc + c + b + + diff --git a/tests/cxx/hybrid/clone/test.xsd b/tests/cxx/hybrid/clone/test.xsd new file mode 100644 index 0000000..cc4bc12 --- /dev/null +++ b/tests/cxx/hybrid/clone/test.xsd @@ -0,0 +1,148 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/tests/cxx/hybrid/makefile b/tests/cxx/hybrid/makefile index 8fb3f3f..88d89a2 100644 --- a/tests/cxx/hybrid/makefile +++ b/tests/cxx/hybrid/makefile @@ -10,7 +10,8 @@ include $(dir $(lastword $(MAKEFILE_LIST)))../../../build/bootstrap.make # all_tests := sequences polymorphism iterator built-in default enumeration \ -iso8859-1 list recursive test-template union binary/cdr binary/xdr choice +iso8859-1 list recursive test-template union binary/cdr binary/xdr choice \ +clone build_tests := sequences @@ -40,7 +41,7 @@ build_tests += binary/xdr endif ifeq ($(xsde_parser_validation),y) -build_tests += choice recursive +build_tests += choice recursive clone endif endif # xsde_iostream 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