aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBoris Kolpackov <boris@codesynthesis.com>2010-01-22 15:40:12 +0200
committerBoris Kolpackov <boris@codesynthesis.com>2010-01-22 15:40:12 +0200
commitf60df03e3cedb86508645357e17003eb9281f31a (patch)
treed65c9cd62a6500b7d0f8303caf64797d08f508c0
parent55ffb84acf75d3fa475dfe21d053e404eb753e5a (diff)
Add support for detaching subtrees in C++/Tree
New option: --generate-detach. New test: cxx/tree/detach.
-rw-r--r--NEWS9
-rw-r--r--documentation/cxx/tree/manual/index.xhtml89
-rw-r--r--documentation/xsd.17
-rw-r--r--documentation/xsd.xhtml7
-rw-r--r--libxsd/xsd/cxx/tree/containers.hxx59
-rw-r--r--libxsd/xsd/cxx/tree/elements.hxx58
-rw-r--r--tests/cxx/tree/detach/driver.cxx101
-rw-r--r--tests/cxx/tree/detach/makefile82
-rw-r--r--tests/cxx/tree/detach/test.xsd32
-rw-r--r--tests/cxx/tree/makefile1
-rw-r--r--xsd/cxx/tree/cli.hxx2
-rw-r--r--xsd/cxx/tree/elements.cxx3
-rw-r--r--xsd/cxx/tree/elements.hxx9
-rw-r--r--xsd/cxx/tree/generator.cxx5
-rw-r--r--xsd/cxx/tree/name-processor.cxx47
-rw-r--r--xsd/cxx/tree/tree-header.cxx52
-rw-r--r--xsd/cxx/tree/tree-inline.cxx24
17 files changed, 550 insertions, 37 deletions
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:
};
</pre>
+ <p>In addition, if requested by specifying the <code>--generate-detach</code>
+ 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:</p>
+
+ <pre class="c++">
+class object: xml_schema::type
+{
+public:
+ ...
+
+ std::auto_ptr&lt;member_type>
+ detach_member ();
+ ...
+
+};
+ </pre>
+
+ <p>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.</p>
<p>The following code shows how one could use this mapping:</p>
@@ -2746,14 +2767,16 @@ f (object&amp; o)
{
using xml_schema::string;
- string s (o.member ()); // get
+ string s (o.member ()); // get
object::member_type&amp; 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&lt;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
}
</pre>
@@ -2907,6 +2930,11 @@ public:
void
set (std::auto_ptr&lt;X>);
+ // Detach and return the contained value.
+ //
+ std::auto_ptr&lt;X>
+ detach ();
+
void
reset ();
};
@@ -2968,6 +2996,9 @@ f (object&amp; 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
}
</pre>
@@ -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 <code>std::vector</code>. 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 <code>std::vector</code>. Two notable extensions
+ to the standard interface that are available only for
+ sequences of non-fundamental C++ types are the addition of
the overloaded <code>push_back</code> and <code>insert</code>
- 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.
- </p>
+ as well as the <code>detach_back</code> and <code>detach</code>
+ member functions. The additional <code>push_back</code> and
+ <code>insert</code> 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 <code>detach_back</code> and
+ <code>detach</code> 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:</p>
+
+ <pre class="c++">
+template &lt;typename X>
+class sequence
+{
+public:
+ ...
+
+ void
+ push_back (std::auto_ptr&lt;X>)
+
+ iterator
+ insert (iterator position, std::auto_ptr&lt;X>)
+
+ std::auto_ptr&lt;X>
+ detach_back (bool pop = true);
+
+ iterator
+ detach (iterator position,
+ std::auto_ptr&lt;X>&amp; result,
+ bool erase = true)
+
+ ...
+}
+ </pre>
<p>The following code shows how one could use this mapping:</p>
@@ -3074,7 +3135,9 @@ f (object&amp; o)
s.push_back ("hello"); // deep copy
std::auto_ptr&lt;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 @@
<dd>Generate constructors that expect an instance of a base type
followed by all required members.</dd>
+ <dt><code><b>--generate-detach</b></code></dt>
+ <dd>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.</dd>
+
<dt><code><b>--generate-wildcard</b></code></dt>
<dd>Generate accessors and modifiers as well as parsing and serialization
code for XML Schema wildcards (<code><b>any</b></code> 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 <cstddef> // std::ptrdiff_t
#include <string>
#include <vector>
@@ -169,6 +168,15 @@ namespace xsd
return x_ != 0;
}
+ std::auto_ptr<T>
+ detach ()
+ {
+ T* x (x_);
+ x->_container (0);
+ x_ = 0;
+ return std::auto_ptr<T> (x);
+ }
+
protected:
T* x_;
flags flags_;
@@ -332,6 +340,15 @@ namespace xsd
void
reset ();
+ std::auto_ptr<T>
+ detach ()
+ {
+ T* x (x_);
+ x->_container (0);
+ x_ = 0;
+ return std::auto_ptr<T> (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<T>
+ detach_back (bool pop = true)
+ {
+ ptr& p (v_.back ());
+ p->_container (0);
+ T* x (static_cast<T*> (p.release ()));
+
+ if (pop)
+ v_.pop_back ();
+
+ return std::auto_ptr<T> (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<T>& r, bool erase = true)
+ {
+ ptr& p (*position.base ());
+ p->_container (0);
+ r.reset (static_cast<T*> (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<map>& m (dr ? dr->map_ : map_);
- if (r->map_.get () != 0)
+ if (container_ == 0)
+ {
+ if (c != 0 && map_.get () != 0)
+ {
+ // Transfer our IDs to the new root.
+ //
+ if (m.get () != 0)
{
- r->map_->insert (map_->begin (), map_->end ());
+ m->insert (map_->begin (), map_->end ());
map_.reset ();
}
else
- r->map_ = map_;
+ m = map_;
}
+ }
+ else
+ {
+ container* sr (_root ());
- container_ = c;
+ if (sr->map_.get () != 0)
+ {
+ // Transfer IDs that belong to this subtree.
+ //
+ for (map::iterator i (sr->map_->begin ()), e (sr->map_->end ());
+ i != e;)
+ {
+ type* x (i->second);
+ for (; x != this && x != sr; x = x->_container ()) ;
+
+ if (x != sr)
+ {
+ // Part of our subtree.
+ //
+ if (m.get () == 0)
+ m.reset (new map);
+
+ m->insert (*i);
+ sr->map_->erase (i++);
+ }
+ else
+ ++i;
+ }
+ }
}
+
+ container_ = c;
}
/**
diff --git a/tests/cxx/tree/detach/driver.cxx b/tests/cxx/tree/detach/driver.cxx
new file mode 100644
index 0000000..afcb90d
--- /dev/null
+++ b/tests/cxx/tree/detach/driver.cxx
@@ -0,0 +1,101 @@
+// file : tests/cxx/tree/detach/driver.cxx
+// author : Boris Kolpackov <boris@codesynthesis.com>
+// copyright : Copyright (c) 2006-2010 Code Synthesis Tools CC
+// license : GNU GPL v2 + exceptions; see accompanying LICENSE file
+
+// Test the detach functionality.
+//
+
+#include <memory> // std::auto_ptr
+#include <cassert>
+
+#include "test.hxx"
+
+using namespace std;
+using namespace test;
+
+int
+main ()
+{
+ // Construct the model.
+ //
+ object o1 ("o1");
+ o1.data ().push_back ("1-1");
+ o1.data ().push_back ("1-2");
+ o1.data ().push_back ("1-3");
+
+ object o2 ("o2");
+ o1.data ().push_back ("2-1");
+ o1.data ().push_back ("2-2");
+ o1.data ().push_back ("2-3");
+
+ object o3 ("o3");
+ o1.data ().push_back ("3-1");
+ o1.data ().push_back ("3-2");
+ o1.data ().push_back ("3-3");
+
+ object o4 ("o4");
+ o1.data ().push_back ("4-1");
+ o1.data ().push_back ("4-2");
+ o1.data ().push_back ("4-3");
+
+ subtree s1;
+ s1.o ().push_back (o1);
+ s1.o ().push_back (o2);
+ s1.r ().push_back (ref ("o2"));
+ s1.r ().push_back (ref ("o3"));
+
+ subtree s2;
+ s2.o ().push_back (o3);
+ s2.o ().push_back (o4);
+ s2.r ().push_back (ref ("o4"));
+ s2.r ().push_back (ref ("o1"));
+
+ model m;
+ m.one (s1);
+ m.opt (s2);
+
+ // Detach one.
+ //
+ auto_ptr<subtree> p (m.detach_one ());
+ assert (p->_container () == 0);
+ assert (p->r ()[0].get () == &p->o ()[1]);
+ assert (m.opt ()->r ()[1].get () == 0);
+
+ m.one (p);
+ assert (m.opt ()->r ()[1].get () == &m.one ().o ()[0]);
+ p = m.detach_one ();
+
+ model m1;
+ m1.one (p);
+ m1.opt (s2);
+ assert (m1.opt ()->r ()[1].get () == &m1.one ().o ()[0]);
+
+ p = m1.detach_one ();
+ m.seq ().push_back (p);
+
+ // Detach opt.
+ //
+ p = m.opt ().detach ();
+ assert (!m.opt ());
+ assert (p->_container () == 0);
+ assert (p->r ()[0].get () == &p->o ()[1]);
+ assert (m.seq ()[0].r ()[1].get () == 0);
+
+ m.seq ().push_back (p);
+
+ // Detach seq.
+ //
+ p = m.seq ().detach_back ();
+ assert (p->_container () == 0);
+ assert (p->r ()[0].get () == &p->o ()[1]);
+ assert (m.seq ()[0].r ()[1].get () == 0);
+
+ m.seq ().push_back (p);
+ assert (m.seq ()[0].r ()[1].get () == &m.seq ()[1].o ()[0]);
+
+ m.seq ().detach (m.seq ().begin (), p);
+ assert (p->_container () == 0);
+ assert (p->r ()[0].get () == &p->o ()[1]);
+ assert (m.seq ()[0].r ()[1].get () == 0);
+}
diff --git a/tests/cxx/tree/detach/makefile b/tests/cxx/tree/detach/makefile
new file mode 100644
index 0000000..938fba2
--- /dev/null
+++ b/tests/cxx/tree/detach/makefile
@@ -0,0 +1,82 @@
+# file : tests/cxx/tree/detach/makefile
+# author : Boris Kolpackov <boris@codesynthesis.com>
+# 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))
+dep := $(obj:.o=.o.d)
+
+driver := $(out_base)/driver
+test := $(out_base)/.test
+clean := $(out_base)/.clean
+
+
+# Import.
+#
+$(call import,\
+ $(scf_root)/import/libxerces-c/stub.make,\
+ l: xerces_c.l,cpp-options: xerces_c.l.cpp-options)
+
+
+# Build.
+#
+$(driver): $(obj) $(xerces_c.l)
+
+$(obj) $(dep): cpp_options := -I$(src_root)/libxsd
+$(obj) $(dep): $(xerces_c.l.cpp-options)
+
+genf := $(xsd:.xsd=.hxx) $(xsd:.xsd=.ixx) $(xsd:.xsd=.cxx)
+gen := $(addprefix $(out_base)/,$(genf))
+
+$(gen): xsd := $(out_root)/xsd/xsd
+$(gen): xsd_options := --generate-detach --generate-default-ctor
+$(gen): $(out_root)/xsd/xsd
+
+$(call include-dep,$(dep))
+
+# Convenience alias for default target.
+#
+$(out_base)/: $(driver)
+
+
+# Test.
+#
+$(test): driver := $(driver)
+$(test): $(driver)
+ $(call message,test $$1,$$1,$(driver))
+
+# 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)/xsd/tree/xsd-cxx.make)
+
+
+# Dependencies.
+#
+$(call import,$(src_root)/xsd/makefile)
diff --git a/tests/cxx/tree/detach/test.xsd b/tests/cxx/tree/detach/test.xsd
new file mode 100644
index 0000000..b9f5166
--- /dev/null
+++ b/tests/cxx/tree/detach/test.xsd
@@ -0,0 +1,32 @@
+<?xml version="1.0"?>
+<schema xmlns="http://www.w3.org/2001/XMLSchema" xmlns:t="test" targetNamespace="test">
+
+ <complexType name="object">
+ <sequence>
+ <element name="data" type="string" maxOccurs="unbounded"/>
+ </sequence>
+ <attribute name="id" type="ID" use="required"/>
+ </complexType>
+
+ <complexType name="ref">
+ <simpleContent>
+ <extension base="IDREF"/>
+ </simpleContent>
+ </complexType>
+
+ <complexType name="subtree">
+ <sequence>
+ <element name="o" type="t:object" minOccurs="0" maxOccurs="unbounded"/>
+ <element name="r" type="t:ref" minOccurs="0" maxOccurs="unbounded"/>
+ </sequence>
+ </complexType>
+
+ <complexType name="model">
+ <sequence>
+ <element name="one" type="t:subtree"/>
+ <element name="opt" type="t:subtree" minOccurs="0"/>
+ <element name="seq" type="t:subtree" minOccurs="0" maxOccurs="unbounded"/>
+ </sequence>
+ </complexType>
+
+</schema>
diff --git a/tests/cxx/tree/makefile b/tests/cxx/tree/makefile
index da848e8..9b79424 100644
--- a/tests/cxx/tree/makefile
+++ b/tests/cxx/tree/makefile
@@ -13,6 +13,7 @@ compilation \
complex \
containment \
default \
+detach \
encoding \
enumeration \
float \
diff --git a/xsd/cxx/tree/cli.hxx b/xsd/cxx/tree/cli.hxx
index c4294b6..171711d 100644
--- a/xsd/cxx/tree/cli.hxx
+++ b/xsd/cxx/tree/cli.hxx
@@ -36,6 +36,7 @@ namespace CXX
extern Key generate_comparison;
extern Key generate_default_ctor;
extern Key generate_from_base_ctor;
+ extern Key generate_detach;
extern Key generate_wildcard;
extern Key generate_insertion;
extern Key generate_extraction;
@@ -134,6 +135,7 @@ namespace CXX
generate_comparison, Boolean,
generate_default_ctor, Boolean,
generate_from_base_ctor, Boolean,
+ generate_detach, Boolean,
generate_wildcard, Boolean,
generate_insertion, Cult::Containers::Vector<NarrowString>,
generate_extraction, Cult::Containers::Vector<NarrowString>,
diff --git a/xsd/cxx/tree/elements.cxx b/xsd/cxx/tree/elements.cxx
index 0072e07..aafc442 100644
--- a/xsd/cxx/tree/elements.cxx
+++ b/xsd/cxx/tree/elements.cxx
@@ -86,6 +86,7 @@ namespace CXX
doxygen (doxygen_),
polymorphic (ops.value<CLI::generate_polymorphic> ()),
polymorphic_all (ops.value<CLI::polymorphic_type_all> ()),
+ detach (ops.value<CLI::generate_detach> ()),
fwd_expr (fe),
hxx_expr (he),
ixx_expr (ie),
@@ -324,6 +325,7 @@ namespace CXX
doxygen (c.doxygen),
polymorphic (c.polymorphic),
polymorphic_all (c.polymorphic_all),
+ detach (c.detach),
fwd_expr (c.fwd_expr),
hxx_expr (c.hxx_expr),
ixx_expr (c.ixx_expr),
@@ -364,6 +366,7 @@ namespace CXX
doxygen (c.doxygen),
polymorphic (c.polymorphic),
polymorphic_all (c.polymorphic_all),
+ detach (c.detach),
fwd_expr (c.fwd_expr),
hxx_expr (c.hxx_expr),
ixx_expr (c.ixx_expr),
diff --git a/xsd/cxx/tree/elements.hxx b/xsd/cxx/tree/elements.hxx
index 2160baf..d081139 100644
--- a/xsd/cxx/tree/elements.hxx
+++ b/xsd/cxx/tree/elements.hxx
@@ -213,6 +213,14 @@ namespace CXX
return a.context ().get<String> ("mname");
}
+ // Detach name.
+ //
+ static String const&
+ edname (SemanticGraph::Member const& m)
+ {
+ return m.context ().get<String> ("dname");
+ }
+
//
//
static String const&
@@ -413,6 +421,7 @@ namespace CXX
Boolean& doxygen;
Boolean polymorphic;
Boolean polymorphic_all;
+ Boolean detach;
Regex const* fwd_expr;
Regex const* hxx_expr;
diff --git a/xsd/cxx/tree/generator.cxx b/xsd/cxx/tree/generator.cxx
index a70214c..ae86767 100644
--- a/xsd/cxx/tree/generator.cxx
+++ b/xsd/cxx/tree/generator.cxx
@@ -129,6 +129,7 @@ namespace CXX
extern Key generate_comparison = "generate-comparison";
extern Key generate_default_ctor = "generate-default-ctor";
extern Key generate_from_base_ctor = "generate-from-base-ctor";
+ extern Key generate_detach = "generate-detach";
extern Key generate_wildcard = "generate-wildcard";
extern Key generate_insertion = "generate-insertion";
extern Key generate_extraction = "generate-extraction";
@@ -283,6 +284,10 @@ namespace CXX
<< " Generate from-base constructors."
<< endl;
+ e << "--generate-detach" << endl
+ << " Generate detach functions for required members."
+ << endl;
+
e << "--generate-wildcard" << endl
<< " Generate accessors/modifiers as well as parsing\n"
<< " and serialization code for XML Schema wildcards."
diff --git a/xsd/cxx/tree/name-processor.cxx b/xsd/cxx/tree/name-processor.cxx
index 1949c5d..a9427a6 100644
--- a/xsd/cxx/tree/name-processor.cxx
+++ b/xsd/cxx/tree/name-processor.cxx
@@ -31,9 +31,6 @@ namespace CXX
//
typedef Cult::Containers::Set<String> NameSet;
-
-
-
class Context: public Tree::Context
{
public:
@@ -57,6 +54,7 @@ namespace CXX
0),
global_type_names (global_type_names_),
global_element_names (global_element_names_),
+ detach (options.value<CLI::generate_detach> ()),
type_regex (type_regex_),
accessor_regex (accessor_regex_),
one_accessor_regex (one_accessor_regex_),
@@ -189,6 +187,7 @@ namespace CXX
//
modifier_regex.push_back ("/([^,]+),([^,]+)/set\\u$1\\u$2/");
modifier_regex.push_back ("/([^,]+)/set\\u$1/");
+ modifier_regex.push_back ("/detach,([^,]+)/detach\\u$1/");
}
compile_regex (options.value<CLI::modifier_regex> (),
@@ -271,6 +270,7 @@ namespace CXX
: Tree::Context (c),
global_type_names (c.global_type_names),
global_element_names (c.global_element_names),
+ detach (c.detach),
type_regex (c.type_regex),
accessor_regex (c.accessor_regex),
one_accessor_regex (c.one_accessor_regex),
@@ -537,6 +537,8 @@ namespace CXX
Cult::Containers::Map<String, NameSet>& global_type_names;
Cult::Containers::Map<String, NameSet>& global_element_names;
+ Boolean detach;
+
RegexVector& type_regex;
RegexVector& accessor_regex;
RegexVector& one_accessor_regex;
@@ -670,8 +672,8 @@ namespace CXX
Boolean def_attr (m.default_ () &&
m.is_a<SemanticGraph::Attribute> ());
- // Accessors/modifiers. Note that we postpone inserting the
- // names into the name_set to avoid over-escaping.
+ // Accessors/modifiers. Note that we postpone inserting
+ // the names into the name_set to avoid over-escaping.
//
String an, mn;
@@ -741,6 +743,19 @@ namespace CXX
if (mn != b && mn != an)
name_set_.insert (mn);
+ // Detach.
+ //
+ if (detach && max == 1 && (min == 1 || def_attr))
+ {
+ String dn (find_name (
+ escape (process_regex (L"detach," + s,
+ one_modifier_regex,
+ modifier_regex,
+ L"one modifier")),
+ name_set_));
+
+ m.context ().set ("dname", dn);
+ }
// Types.
//
@@ -1281,21 +1296,21 @@ namespace CXX
escape (process_regex (L"value,traits", type_regex, L"type")),
set));
- String an = Context::find_name (
+ String an (Context::find_name (
escape (process_regex ("value",
one_accessor_regex,
accessor_regex,
L"one accessor")),
set,
- false);
+ false));
- String mn = Context::find_name (
+ String mn (Context::find_name (
escape (process_regex ("value",
one_modifier_regex,
modifier_regex,
L"one modifier")),
set,
- false);
+ false));
ec.set ("aname", an);
ec.set ("mname", mn);
@@ -1305,6 +1320,20 @@ namespace CXX
if (an != mn)
set.insert (mn);
+ // Detach.
+ //
+ if (detach)
+ {
+ String dn (Context::find_name (
+ escape (process_regex (L"detach,value",
+ one_modifier_regex,
+ modifier_regex,
+ L"one modifier")),
+ set));
+
+ ec.set ("dname", dn);
+ }
+
// Assign name() and namespace_() names.
//
ec.set (
diff --git a/xsd/cxx/tree/tree-header.cxx b/xsd/cxx/tree/tree-header.cxx
index 7e884c8..100a81c 100644
--- a/xsd/cxx/tree/tree-header.cxx
+++ b/xsd/cxx/tree/tree-header.cxx
@@ -1332,14 +1332,39 @@ namespace CXX
<< " * @param p A new value to use." << endl
<< " *" << endl
<< " * This function will try to use the passed value " <<
- "directly instead" << endl
- << " * of making a copy." << endl
+ "directly" << endl
+ << " * instead of making a copy." << endl
<< " */" << endl;
}
os << "void" << endl
<< mname << " (::std::auto_ptr< " << type << " > p);"
<< endl;
+
+ }
+
+ // auto_ptr<type>
+ // detach_name ();
+ //
+ if (detach && !fund)
+ {
+ if (doxygen)
+ {
+ os << "/**" << endl
+ << " * @brief Detach the " << kind << " value from " <<
+ "the object model." << endl
+ << " *" << endl
+ << " * @return A pointer to the " << kind << " value." << endl
+ << " *" << endl
+ << " * Note that this function leaves the required " <<
+ kind << " in " << endl
+ << " * the original object model uninitialized." << endl
+ << " */" << endl;
+ }
+
+ os << "::std::auto_ptr< " << type << " >" << endl
+ << edname (m) << " ();"
+ << endl;
}
}
}
@@ -3247,6 +3272,29 @@ namespace CXX
<< endl;
}
+ // auto_ptr<type>
+ // detach_name ();
+ //
+ if (detach && !fund)
+ {
+ if (doxygen)
+ {
+ os << "/**" << endl
+ << " * @brief Detach the element value from " <<
+ "the object." << endl
+ << " *" << endl
+ << " * @return A pointer to the element value." << endl
+ << " *" << endl
+ << " * Note that this function leaves the element " <<
+ "object uninitialized." << endl
+ << " */" << endl;
+ }
+
+ os << "::std::auto_ptr< " << type << " >" << endl
+ << edname (e) << " ();"
+ << endl;
+ }
+
if (doxygen)
{
os << "/**" << endl
diff --git a/xsd/cxx/tree/tree-inline.cxx b/xsd/cxx/tree/tree-inline.cxx
index a075d3f..6a983af 100644
--- a/xsd/cxx/tree/tree-inline.cxx
+++ b/xsd/cxx/tree/tree-inline.cxx
@@ -593,6 +593,18 @@ namespace CXX
<< "{"
<< "this->" << member << ".set (x);"
<< "}";
+
+ // auto_ptr<type>
+ // detach_name ();
+ //
+ if (detach && !fund)
+ os << inl
+ << "::std::auto_ptr< " << q_type << " > " <<
+ scope_ << "::" << endl
+ << edname (m) << " ()"
+ << "{"
+ << "return this->" << member << ".detach ();"
+ << "}";
}
}
@@ -979,6 +991,18 @@ namespace CXX
<< "return this->" << member << ".set (p);"
<< "}";
}
+
+ // auto_ptr<type>
+ // detach_name ();
+ //
+ if (detach && !fund)
+ os << inl
+ << "::std::auto_ptr< " << name << "::" << type << " > " <<
+ name << "::" << endl
+ << edname (e) << " ()"
+ << "{"
+ << "return this->" << member << ".detach ();"
+ << "}";
}
};
}