aboutsummaryrefslogtreecommitdiff
path: root/libxsd/xsd/cxx/tree
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 /libxsd/xsd/cxx/tree
parent55ffb84acf75d3fa475dfe21d053e404eb753e5a (diff)
Add support for detaching subtrees in C++/Tree
New option: --generate-detach. New test: cxx/tree/detach.
Diffstat (limited to 'libxsd/xsd/cxx/tree')
-rw-r--r--libxsd/xsd/cxx/tree/containers.hxx59
-rw-r--r--libxsd/xsd/cxx/tree/elements.hxx58
2 files changed, 104 insertions, 13 deletions
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;
}
/**