diff options
author | Boris Kolpackov <boris@codesynthesis.com> | 2010-01-22 15:40:12 +0200 |
---|---|---|
committer | Boris Kolpackov <boris@codesynthesis.com> | 2010-01-22 15:40:12 +0200 |
commit | f60df03e3cedb86508645357e17003eb9281f31a (patch) | |
tree | d65c9cd62a6500b7d0f8303caf64797d08f508c0 /libxsd | |
parent | 55ffb84acf75d3fa475dfe21d053e404eb753e5a (diff) |
Add support for detaching subtrees in C++/Tree
New option: --generate-detach. New test: cxx/tree/detach.
Diffstat (limited to 'libxsd')
-rw-r--r-- | libxsd/xsd/cxx/tree/containers.hxx | 59 | ||||
-rw-r--r-- | libxsd/xsd/cxx/tree/elements.hxx | 58 |
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; } /** |