From f60df03e3cedb86508645357e17003eb9281f31a Mon Sep 17 00:00:00 2001
From: Boris Kolpackov
Date: Fri, 22 Jan 2010 15:40:12 +0200
Subject: Add support for detaching subtrees in C++/Tree
New option: --generate-detach. New test: cxx/tree/detach.
---
NEWS | 9 +++
documentation/cxx/tree/manual/index.xhtml | 89 ++++++++++++++++++++++----
documentation/xsd.1 | 7 +++
documentation/xsd.xhtml | 7 +++
libxsd/xsd/cxx/tree/containers.hxx | 59 ++++++++++++++++-
libxsd/xsd/cxx/tree/elements.hxx | 58 +++++++++++++----
tests/cxx/tree/detach/driver.cxx | 101 ++++++++++++++++++++++++++++++
tests/cxx/tree/detach/makefile | 82 ++++++++++++++++++++++++
tests/cxx/tree/detach/test.xsd | 32 ++++++++++
tests/cxx/tree/makefile | 1 +
xsd/cxx/tree/cli.hxx | 2 +
xsd/cxx/tree/elements.cxx | 3 +
xsd/cxx/tree/elements.hxx | 9 +++
xsd/cxx/tree/generator.cxx | 5 ++
xsd/cxx/tree/name-processor.cxx | 47 +++++++++++---
xsd/cxx/tree/tree-header.cxx | 52 ++++++++++++++-
xsd/cxx/tree/tree-inline.cxx | 24 +++++++
17 files changed, 550 insertions(+), 37 deletions(-)
create mode 100644 tests/cxx/tree/detach/driver.cxx
create mode 100644 tests/cxx/tree/detach/makefile
create mode 100644 tests/cxx/tree/detach/test.xsd
diff --git a/NEWS b/NEWS
index 956a9fd..d202c00 100644
--- a/NEWS
+++ b/NEWS
@@ -56,6 +56,15 @@ Version 3.3.0
on this change see Section 2.11, "Mapping for xsi:type and Substitution
Groups" in the C++/Tree Mapping User Manual.
+ * New option, --generate-detach, triggers generation of detach functions
+ for required elements and attributes. For optional and sequence
+ cardinalities the detach functions are now provided by the respective
+ containers even without this option. These functions, for example,
+ allow one to move sub-trees in the object model either within the
+ same tree or between different trees without copying. For more
+ information refer to Section 2.8 "Mapping for Local Elements and
+ Attributes" in the C++/Tree Mapping User Manual.
+
* New option, --export-xml-schema, causes the compiler to export/import
types in the XML Schema namespace using the export symbol provided
with the --export-symbol option.
diff --git a/documentation/cxx/tree/manual/index.xhtml b/documentation/cxx/tree/manual/index.xhtml
index c00be9e..695a72e 100644
--- a/documentation/cxx/tree/manual/index.xhtml
+++ b/documentation/cxx/tree/manual/index.xhtml
@@ -2737,6 +2737,27 @@ public:
};
+ In addition, if requested by specifying the --generate-detach
+ option and only for members of non-fundamental C++ types, the mapping
+ provides a detach function that returns an automatic pointer to the
+ member's type, for example:
+
+
+class object: xml_schema::type
+{
+public:
+ ...
+
+ std::auto_ptr<member_type>
+ detach_member ();
+ ...
+
+};
+
+
+ This function detaches the value from the tree leaving the member
+ value uninitialized. Accessing such an uninitialized value prior to
+ re-initializing it results in undefined behavior.
The following code shows how one could use this mapping:
@@ -2746,14 +2767,16 @@ f (object& o)
{
using xml_schema::string;
- string s (o.member ()); // get
+ string s (o.member ()); // get
object::member_type& sr (o.member ()); // get
- o.member ("hello"); // set, deep copy
- o.member () = "hello"; // set, deep copy
+ o.member ("hello"); // set, deep copy
+ o.member () = "hello"; // set, deep copy
std::auto_ptr<string> p (new string ("hello"));
- o.member (p); // set, assumes ownership
+ o.member (p); // set, assumes ownership
+ p = o.detach_member (); // detach, member is uninitialized
+ o.member (p); // re-attach
}
@@ -2907,6 +2930,11 @@ public:
void
set (std::auto_ptr<X>);
+ // Detach and return the contained value.
+ //
+ std::auto_ptr<X>
+ detach ();
+
void
reset ();
};
@@ -2968,6 +2996,9 @@ f (object& o)
p = new string ("hello");
o.member ().set (p); // set, assumes ownership
+
+ p = o.member ().detach (); // detach, member is reset
+ o.member ().set (p); // re-attach
}
@@ -3042,15 +3073,45 @@ public:
sequence interface as defined by the ISO/ANSI Standard for
C++ (ISO/IEC 14882:1998, Section 23.1.1, "Sequences").
Practically, this means that you can treat such a sequence
- as if it was std::vector
. One notable extension
- to the standard interface that is available only for
- sequences of non-fundamental C++ types is the addition of
+ as if it was std::vector
. Two notable extensions
+ to the standard interface that are available only for
+ sequences of non-fundamental C++ types are the addition of
the overloaded push_back
and insert
- member functions which instead of the constant reference
- to the element type accept automatic pointer to the element
- type. These functions assume ownership of the pointed to
- object and resets the passed automatic pointer.
-
+ as well as the detach_back
and detach
+ member functions. The additional push_back
and
+ insert
functions accept an automatic pointer to the
+ element type instead of the constant reference. They assume
+ ownership of the pointed to object and resets the passed
+ automatic pointer. The detach_back
and
+ detach
functions detach the element
+ value from the sequence container and, by default, remove
+ the element from the sequence. These additional functions
+ have the following signatures:
+
+
+template <typename X>
+class sequence
+{
+public:
+ ...
+
+ void
+ push_back (std::auto_ptr<X>)
+
+ iterator
+ insert (iterator position, std::auto_ptr<X>)
+
+ std::auto_ptr<X>
+ detach_back (bool pop = true);
+
+ iterator
+ detach (iterator position,
+ std::auto_ptr<X>& result,
+ bool erase = true)
+
+ ...
+}
+
The following code shows how one could use this mapping:
@@ -3074,7 +3135,9 @@ f (object& o)
s.push_back ("hello"); // deep copy
std::auto_ptr<string> p (new string ("hello"));
- s.push_back (o); // assumes ownership
+ s.push_back (p); // assumes ownership
+ p = s.detach_back (); // detach and pop
+ s.push_back (p); // re-append
// Setting a new container.
//
diff --git a/documentation/xsd.1 b/documentation/xsd.1
index 762d865..7536bb6 100644
--- a/documentation/xsd.1
+++ b/documentation/xsd.1
@@ -800,6 +800,13 @@ not initialized and accessing them results in undefined behavior.
Generate constructors that expect an instance of a base type followed by all
required members.
+.IP "\fB\--generate-detach\fR"
+Generate detach functions for required elements and attributes (detach
+functions for optional and sequence cardinalities are provided by the
+respective containers). These functions, for example, allow you to move
+sub-trees in the object model either within the same tree or between
+different trees.
+
.IP "\fB\--generate-wildcard\fR"
Generate accessors and modifiers as well as parsing and serialization code
for XML Schema wildcards
diff --git a/documentation/xsd.xhtml b/documentation/xsd.xhtml
index 46e8c1a..1330509 100644
--- a/documentation/xsd.xhtml
+++ b/documentation/xsd.xhtml
@@ -711,6 +711,13 @@
Generate constructors that expect an instance of a base type
followed by all required members.
+ --generate-detach
+ Generate detach functions for required elements and attributes
+ (detach functions for optional and sequence cardinalities are
+ provided by the respective containers). These functions, for
+ example, allow you to move sub-trees in the object model either
+ within the same tree or between different trees.
+
--generate-wildcard
Generate accessors and modifiers as well as parsing and serialization
code for XML Schema wildcards (any
and
diff --git a/libxsd/xsd/cxx/tree/containers.hxx b/libxsd/xsd/cxx/tree/containers.hxx
index 1399c5d..8ea04d2 100644
--- a/libxsd/xsd/cxx/tree/containers.hxx
+++ b/libxsd/xsd/cxx/tree/containers.hxx
@@ -6,7 +6,6 @@
#ifndef XSD_CXX_TREE_CONTAINERS_HXX
#define XSD_CXX_TREE_CONTAINERS_HXX
-
#include // std::ptrdiff_t
#include
#include
@@ -169,6 +168,15 @@ namespace xsd
return x_ != 0;
}
+ std::auto_ptr
+ detach ()
+ {
+ T* x (x_);
+ x->_container (0);
+ x_ = 0;
+ return std::auto_ptr (x);
+ }
+
protected:
T* x_;
flags flags_;
@@ -332,6 +340,15 @@ namespace xsd
void
reset ();
+ std::auto_ptr
+ detach ()
+ {
+ T* x (x_);
+ x->_container (0);
+ x_ = 0;
+ return std::auto_ptr (x);
+ }
+
private:
void
true_ ();
@@ -809,11 +826,25 @@ namespace xsd
}
type*
+ operator-> () const
+ {
+ return x_;
+ }
+
+ type*
get () const
{
return x_;
}
+ type*
+ release ()
+ {
+ type* x (x_);
+ x_ = 0;
+ return x;
+ }
+
private:
mutable type* x_;
};
@@ -1247,6 +1278,19 @@ namespace xsd
v_.pop_back ();
}
+ std::auto_ptr
+ detach_back (bool pop = true)
+ {
+ ptr& p (v_.back ());
+ p->_container (0);
+ T* x (static_cast (p.release ()));
+
+ if (pop)
+ v_.pop_back ();
+
+ return std::auto_ptr (x);
+ }
+
iterator
insert (iterator position, const T& x)
{
@@ -1289,6 +1333,19 @@ namespace xsd
return iterator (v_.erase (begin.base (), end.base ()));
}
+ iterator
+ detach (iterator position, std::auto_ptr& r, bool erase = true)
+ {
+ ptr& p (*position.base ());
+ p->_container (0);
+ r.reset (static_cast (p.release ()));
+
+ if (erase)
+ return iterator (v_.erase (position.base ()));
+ else
+ return ++position;
+ }
+
// Note that the container object of the two sequences being
// swapped should be the same.
//
diff --git a/libxsd/xsd/cxx/tree/elements.hxx b/libxsd/xsd/cxx/tree/elements.hxx
index 273e847..598a756 100644
--- a/libxsd/xsd/cxx/tree/elements.hxx
+++ b/libxsd/xsd/cxx/tree/elements.hxx
@@ -419,30 +419,64 @@ namespace xsd
virtual void
_container (container* c)
{
- assert (container_ == 0);
+ container* dr (0);
if (c != 0)
{
- if (map_.get () != 0)
- {
- // Propagate our IDs to the new root.
- //
- container* r (c->_root ());
+ dr = c->_root ();
+
+ if (dr == 0)
+ dr = c;
+ }
- if (r == 0)
- r = c;
+ std::auto_ptr