diff options
Diffstat (limited to 'xsd/libxsd/xsd/cxx/tree/containers-wildcard.hxx')
-rw-r--r-- | xsd/libxsd/xsd/cxx/tree/containers-wildcard.hxx | 1335 |
1 files changed, 1335 insertions, 0 deletions
diff --git a/xsd/libxsd/xsd/cxx/tree/containers-wildcard.hxx b/xsd/libxsd/xsd/cxx/tree/containers-wildcard.hxx new file mode 100644 index 0000000..5313507 --- /dev/null +++ b/xsd/libxsd/xsd/cxx/tree/containers-wildcard.hxx @@ -0,0 +1,1335 @@ +// file : xsd/cxx/tree/containers-wildcard.hxx +// author : Boris Kolpackov <boris@codesynthesis.com> +// copyright : Copyright (c) 2005-2010 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#ifndef XSD_CXX_TREE_CONTAINERS_WILDCARD_HXX +#define XSD_CXX_TREE_CONTAINERS_WILDCARD_HXX + +#include <set> +#include <string> + +#include <xercesc/dom/DOMAttr.hpp> +#include <xercesc/dom/DOMElement.hpp> +#include <xercesc/dom/DOMDocument.hpp> +#include <xercesc/util/XMLString.hpp> + +#include <xsd/cxx/xml/string.hxx> + +#include <xsd/cxx/tree/containers.hxx> // iterator_adapter + +namespace xsd +{ + namespace cxx + { + namespace tree + { + // one (for internal use only) + // + class element_one + { + public: + ~element_one () + { + if (x_) + x_->release (); + } + + explicit + element_one (xercesc::DOMDocument& doc) + : x_ (0), doc_ (doc) + { + } + + element_one (const xercesc::DOMElement& x, xercesc::DOMDocument& doc) + : x_ (0), doc_ (doc) + { + set (x); + } + + element_one (const element_one& x, xercesc::DOMDocument& doc) + : x_ (0), doc_ (doc) + { + if (x.present ()) + set (x.get ()); + } + + element_one& + operator= (const element_one& x) + { + if (this == &x) + return *this; + + if (x.present ()) + set (x.get ()); + else if (x_) + { + x_->release (); + x_ = 0; + } + + return *this; + } + + public: + const xercesc::DOMElement& + get () const + { + return *x_; + } + + xercesc::DOMElement& + get () + { + return *x_; + } + + void + set (const xercesc::DOMElement& x) + { + using xercesc::DOMElement; + + DOMElement* r ( + static_cast<DOMElement*> ( + doc_.importNode (const_cast<DOMElement*> (&x), true))); + + if (x_) + x_->release (); + + x_ = r; + } + + void + set (xercesc::DOMElement* x) + { + assert (x->getOwnerDocument () == &doc_); + + if (x_) + x_->release (); + + x_ = x; + } + + bool + present () const + { + return x_ != 0; + } + + protected: + xercesc::DOMElement* x_; + xercesc::DOMDocument& doc_; + }; + + + // + // + class element_optional + { + public: + ~element_optional () + { + if (x_) + x_->release (); + } + + explicit + element_optional (xercesc::DOMDocument& doc) + : x_ (0), doc_ (doc) + { + } + + element_optional (const xercesc::DOMElement& x, + xercesc::DOMDocument& doc) + : x_ (0), doc_ (doc) + { + set (x); + } + + element_optional (xercesc::DOMElement* x, xercesc::DOMDocument& doc) + : x_ (0), doc_ (doc) + { + set (x); + } + + element_optional (const element_optional& x, + xercesc::DOMDocument& doc) + : x_ (0), doc_ (doc) + { + if (x) + set (*x); + } + + element_optional& + operator= (const xercesc::DOMElement& x) + { + if (x_ == &x) + return *this; + + set (x); + + return *this; + } + + element_optional& + operator= (const element_optional& x) + { + if (this == &x) + return *this; + + if (x) + set (*x); + else + reset (); + + return *this; + } + + // Pointer-like interface. + // + public: + const xercesc::DOMElement* + operator-> () const + { + return x_; + } + + xercesc::DOMElement* + operator-> () + { + return x_; + } + + const xercesc::DOMElement& + operator* () const + { + return *x_; + } + + xercesc::DOMElement& + operator* () + { + return *x_; + } + + typedef void (element_optional::*bool_convertible) (); + + operator bool_convertible () const + { + return x_ != 0 ? &element_optional::true_ : 0; + } + + // Get/set interface. + // + public: + bool + present () const + { + return x_ != 0; + } + + const xercesc::DOMElement& + get () const + { + return *x_; + } + + xercesc::DOMElement& + get () + { + return *x_; + } + + void + set (const xercesc::DOMElement& x) + { + using xercesc::DOMElement; + + DOMElement* r ( + static_cast<DOMElement*> ( + doc_.importNode (const_cast<DOMElement*> (&x), true))); + + if (x_) + x_->release (); + + x_ = r; + } + + void + set (xercesc::DOMElement* x) + { + assert (x->getOwnerDocument () == &doc_); + + if (x_) + x_->release (); + + x_ = x; + } + + void + reset () + { + if (x_) + x_->release (); + + x_ = 0; + } + + private: + void + true_ () + { + } + + private: + xercesc::DOMElement* x_; + xercesc::DOMDocument& doc_; + }; + + // Comparison operators. + // + + inline bool + operator== (const element_optional& a, const element_optional& b) + { + return !a || !b + ? a.present () == b.present () + : a->isEqualNode (&b.get ()); + } + + inline bool + operator!= (const element_optional& a, const element_optional& b) + { + return !(a == b); + } + + + // + // + class element_sequence + { + protected: + // This is a dangerously destructive automatic pointer. We are going + // to use it in a controlled environment to save us a lot of coding. + // + struct ptr + { + ~ptr () + { + if (x_) + x_->release (); + } + + explicit + ptr (xercesc::DOMElement* x = 0) + : x_ (x) + { + } + + ptr (const ptr& y) + : x_ (y.x_) + { + // Yes, hostile takeover. + // + y.x_ = 0; + } + + ptr& + operator= (const ptr& y) + { + if (this != &y) + { + // Yes, hostile takeover. + // + if (x_) + x_->release (); + + x_ = y.x_; + y.x_ = 0; + } + + return *this; + } + + public: + xercesc::DOMElement& + operator* () const + { + return *x_; + } + + xercesc::DOMElement* + get () const + { + return x_; + } + + private: + mutable xercesc::DOMElement* x_; + }; + + typedef std::vector<ptr> base_sequence; + typedef base_sequence::iterator base_iterator; + typedef base_sequence::const_iterator base_const_iterator; + + public: + typedef xercesc::DOMElement value_type; + typedef xercesc::DOMElement* pointer; + typedef const xercesc::DOMElement* const_pointer; + typedef xercesc::DOMElement& reference; + typedef const xercesc::DOMElement& const_reference; + + typedef + iterator_adapter<base_sequence::iterator, xercesc::DOMElement> + iterator; + + typedef + iterator_adapter<base_sequence::const_iterator, + const xercesc::DOMElement> + const_iterator; + + typedef + iterator_adapter<base_sequence::reverse_iterator, xercesc::DOMElement> + reverse_iterator; + + typedef + iterator_adapter<base_sequence::const_reverse_iterator, + const xercesc::DOMElement> + const_reverse_iterator; + + typedef base_sequence::size_type size_type; + typedef base_sequence::difference_type difference_type; + typedef base_sequence::allocator_type allocator_type; + + public: + explicit + element_sequence (xercesc::DOMDocument& doc) + : doc_ (doc) + { + } + + // DOMElement cannot be default-constructed. + // + // explicit + // element_sequence (size_type n); + + element_sequence (size_type n, + const xercesc::DOMElement& x, + xercesc::DOMDocument& doc) + : doc_ (doc) + { + assign (n, x); + } + + template <typename I> + element_sequence (const I& begin, const I& end, + xercesc::DOMDocument& doc) + : doc_ (doc) + { + assign (begin, end); + } + + element_sequence (const element_sequence& v, + xercesc::DOMDocument& doc) + : doc_ (doc) + { + v_.reserve (v.v_.size ()); + + for (base_const_iterator i (v.v_.begin ()), e (v.v_.end ()); + i != e; ++i) + { + ptr p (static_cast<xercesc::DOMElement*> ( + doc_.importNode (i->get (), true))); + + v_.push_back (p); + } + } + + element_sequence& + operator= (const element_sequence& v) + { + if (this == &v) + return *this; + + v_.assign (v.v_.size (), ptr ()); + + base_iterator di (v_.begin ()), de (v_.end ()); + base_const_iterator si (v.v_.begin ()), se (v.v_.end ()); + + for (; si != se && di != de; ++si, ++di) + { + ptr p (static_cast<xercesc::DOMElement*> ( + doc_.importNode (si->get (), true))); + *di = p; + } + + return *this; + } + + public: + void + assign (size_type n, const xercesc::DOMElement& x) + { + v_.assign (n, ptr ()); + + for (base_iterator i (v_.begin ()), e (v_.end ()); i != e; ++i) + { + ptr p (static_cast<xercesc::DOMElement*> ( + doc_.importNode ( + const_cast<xercesc::DOMElement*> (&x), true))); + *i = p; + } + } + + template <typename I> + void + assign (const I& begin, const I& end) + { + // This is not the fastest way to do it. + // + v_.clear (); + + for (I i (begin); i != end; ++i) + { + ptr p (static_cast<xercesc::DOMElement*> ( + doc_.importNode ( + const_cast<xercesc::DOMElement*> (&(*i)), true))); + v_.push_back (p); + } + } + + public: + // This version of resize can only be used to shrink the + // sequence because DOMElement cannot be default-constructed. + // + void + resize (size_type n) + { + assert (n <= v_.size ()); + v_.resize (n, ptr ()); + } + + void + resize (size_type n, const xercesc::DOMElement& x) + { + size_type old (v_.size ()); + v_.resize (n, ptr ()); + + if (old < n) + { + for (base_iterator i (v_.begin () + old), e (v_.end ()); + i != e; ++i) + { + ptr p (static_cast<xercesc::DOMElement*> ( + doc_.importNode ( + const_cast<xercesc::DOMElement*> (&x), true))); + *i = p; + } + } + } + + public: + size_type + size () const + { + return v_.size (); + } + + size_type + max_size () const + { + return v_.max_size (); + } + + size_type + capacity () const + { + return v_.capacity (); + } + + bool + empty () const + { + return v_.empty (); + } + + void + reserve (size_type n) + { + v_.reserve (n); + } + + void + clear () + { + v_.clear (); + } + + public: + const_iterator + begin () const + { + return const_iterator (v_.begin ()); + } + + const_iterator + end () const + { + return const_iterator (v_.end ()); + } + + iterator + begin () + { + return iterator (v_.begin ()); + } + + iterator + end () + { + return iterator (v_.end ()); + } + + // reverse + // + + const_reverse_iterator + rbegin () const + { + return const_reverse_iterator (v_.rbegin ()); + } + + const_reverse_iterator + rend () const + { + return const_reverse_iterator (v_.rend ()); + } + + reverse_iterator + rbegin () + { + return reverse_iterator (v_.rbegin ()); + } + + reverse_iterator + rend () + { + return reverse_iterator (v_.rend ()); + } + + public: + xercesc::DOMElement& + operator[] (size_type n) + { + return *(v_[n]); + } + + const xercesc::DOMElement& + operator[] (size_type n) const + { + return *(v_[n]); + } + + xercesc::DOMElement& + at (size_type n) + { + return *(v_.at (n)); + } + + const xercesc::DOMElement& + at (size_type n) const + { + return *(v_.at (n)); + } + + xercesc::DOMElement& + front () + { + return *(v_.front ()); + } + + const xercesc::DOMElement& + front () const + { + return *(v_.front ()); + } + + xercesc::DOMElement& + back () + { + return *(v_.back ()); + } + + const xercesc::DOMElement& + back () const + { + return *(v_.back ()); + } + + public: + // Makes a deep copy. + // + void + push_back (const xercesc::DOMElement& x) + { + ptr p (static_cast<xercesc::DOMElement*> ( + doc_.importNode ( + const_cast<xercesc::DOMElement*> (&x), true))); + + v_.push_back (p); + } + + // Assumes ownership. + // + void + push_back (xercesc::DOMElement* x) + { + assert (x->getOwnerDocument () == &doc_); + v_.push_back (ptr (x)); + } + + void + pop_back () + { + v_.pop_back (); + } + + // Makes a deep copy. + // + iterator + insert (iterator position, const xercesc::DOMElement& x) + { + ptr p (static_cast<xercesc::DOMElement*> ( + doc_.importNode ( + const_cast<xercesc::DOMElement*> (&x), true))); + + return iterator (v_.insert (position.base (), p)); + } + + // Assumes ownership. + // + iterator + insert (iterator position, xercesc::DOMElement* x) + { + assert (x->getOwnerDocument () == &doc_); + return iterator (v_.insert (position.base (), ptr (x))); + } + + void + insert (iterator position, size_type n, const xercesc::DOMElement& x) + { + difference_type d (v_.end () - position.base ()); + v_.insert (position.base (), n, ptr ()); + + for (base_iterator i (v_.end () - d); n != 0; --n) + { + ptr r (static_cast<xercesc::DOMElement*> ( + doc_.importNode ( + const_cast<xercesc::DOMElement*> (&x), true))); + *(--i) = r; + } + } + + template <typename I> + void + insert (iterator position, const I& begin, const I& end) + { + // This is not the fastest way to do it. + // + if (begin != end) + { + base_iterator p (position.base ()); + + for (I i (end);;) + { + --i; + ptr r (static_cast<xercesc::DOMElement*> ( + doc_.importNode (i->get (), true))); + + p = v_.insert (p, r); + + if (i == begin) + break; + } + } + } + + iterator + erase (iterator position) + { + return iterator (v_.erase (position.base ())); + } + + iterator + erase (iterator begin, iterator end) + { + return iterator (v_.erase (begin.base (), end.base ())); + } + + public: + // Note that the DOMDocument object of the two sequences being + // swapped should be the same. + // + void + swap (element_sequence& x) + { + assert (&doc_ == &x.doc_); + v_.swap (x.v_); + } + + private: + base_sequence v_; + xercesc::DOMDocument& doc_; + }; + + // Comparison operators. + // + + inline bool + operator== (const element_sequence& a, const element_sequence& b) + { + if (a.size () != b.size ()) + return false; + + element_sequence::const_iterator + ai (a.begin ()), ae (a.end ()), bi (b.begin ()); + + for (; ai != ae; ++ai, ++bi) + if (!ai->isEqualNode (&(*bi))) + return false; + + return true; + } + + inline bool + operator!= (const element_sequence& a, const element_sequence& b) + { + return !(a == b); + } + + + // Attribute set. + // + + class attribute_set_common + { + protected: + // Set entry. It can either act as a dangerously destructive + // automatic pointer for DOMAttr or as an entry containing the + // name we are searching for. + // + struct entry + { + ~entry () + { + if (a_) + a_->release (); + } + + explicit + entry (xercesc::DOMAttr* a) + : a_ (a), ns_ (0), name_ (0) + { + ns_ = a->getNamespaceURI (); + name_ = ns_ == 0 ? a->getName () : a->getLocalName (); + } + + // Note: uses shallow copy. + // + explicit + entry (const XMLCh* ns, const XMLCh* name) + : a_ (0), ns_ (ns), name_ (name) + { + } + + entry (const entry& y) + : a_ (y.a_), ns_ (y.ns_), name_ (y.name_) + { + // Yes, hostile takeover. + // + y.a_ = 0; + y.ns_ = 0; + y.name_ = 0; + } + + entry& + operator= (const entry& y) + { + if (this != &y) + { + // Yes, hostile takeover. + // + if (a_) + a_->release (); + + a_ = y.a_; + ns_ = y.ns_; + name_ = y.name_; + + y.a_ = 0; + y.ns_ = 0; + y.name_ = 0; + } + + return *this; + } + + public: + xercesc::DOMAttr& + operator* () const + { + return *a_; + } + + xercesc::DOMAttr* + get () const + { + return a_; + } + + const XMLCh* + ns () const + { + return ns_; + } + + const XMLCh* + name () const + { + return name_; + } + + void + release () + { + a_ = 0; + } + + private: + mutable xercesc::DOMAttr* a_; + mutable const XMLCh* ns_; + mutable const XMLCh* name_; + }; + + struct entry_cmp + { + bool + operator() (const entry& a, const entry& b) const + { + using xercesc::XMLString; + + const XMLCh* ans (a.ns ()); + const XMLCh* bns (b.ns ()); + + const XMLCh* an (a.name ()); + const XMLCh* bn (b.name ()); + + if (ans == 0) + return bns != 0 + ? true + : (XMLString::compareString (an, bn) < 0); + + if (ans != 0 && bns == 0) + return false; + + int r (XMLString::compareString (ans, bns)); + + return r < 0 + ? true + : (r > 0 ? false : XMLString::compareString (an, bn)); + } + }; + + typedef std::set<entry, entry_cmp> base_set; + typedef base_set::iterator base_iterator; + typedef base_set::const_iterator base_const_iterator; + }; + + template <typename C> + class attribute_set: public attribute_set_common + { + public: + typedef xercesc::DOMAttr key_type; + typedef xercesc::DOMAttr value_type; + typedef xercesc::DOMAttr* pointer; + typedef const xercesc::DOMAttr* const_pointer; + typedef xercesc::DOMAttr& reference; + typedef const xercesc::DOMAttr& const_reference; + + typedef + iterator_adapter<base_set::iterator, xercesc::DOMAttr> + iterator; + + typedef + iterator_adapter<base_set::const_iterator, const xercesc::DOMAttr> + const_iterator; + + typedef + iterator_adapter<base_set::reverse_iterator, xercesc::DOMAttr> + reverse_iterator; + + typedef + iterator_adapter<base_set::const_reverse_iterator, + const xercesc::DOMAttr> + const_reverse_iterator; + + typedef base_set::size_type size_type; + typedef base_set::difference_type difference_type; + typedef base_set::allocator_type allocator_type; + + public: + attribute_set (xercesc::DOMDocument& doc) + : doc_ (doc) + { + } + + template <typename I> + attribute_set (const I& begin, + const I& end, + xercesc::DOMDocument& doc) + : doc_ (doc) + { + insert (begin, end); + } + + attribute_set (const attribute_set& s, xercesc::DOMDocument& doc) + : doc_ (doc) + { + // Can be done faster with the "hinted" insert. + // + insert (s.begin (), s.end ()); + } + + attribute_set& + operator= (const attribute_set& s) + { + if (this == &s) + return *this; + + // Can be done faster with the "hinted" insert. + // + clear (); + insert (s.begin (), s.end ()); + + return *this; + } + + public: + const_iterator + begin () const + { + return const_iterator (s_.begin ()); + } + + const_iterator + end () const + { + return const_iterator (s_.end ()); + } + + iterator + begin () + { + return iterator (s_.begin ()); + } + + iterator + end () + { + return iterator (s_.end ()); + } + + // reverse + // + + const_reverse_iterator + rbegin () const + { + return const_reverse_iterator (s_.rbegin ()); + } + + const_reverse_iterator + rend () const + { + return const_reverse_iterator (s_.rend ()); + } + + reverse_iterator + rbegin () + { + return reverse_iterator (s_.rbegin ()); + } + + reverse_iterator + rend () + { + return reverse_iterator (s_.rend ()); + } + + public: + size_type + size () const + { + return s_.size (); + } + + size_type + max_size () const + { + return s_.max_size (); + } + + bool + empty () const + { + return s_.empty (); + } + + void + clear () + { + s_.clear (); + } + + public: + // Makes a deep copy. + // + std::pair<iterator, bool> + insert (const xercesc::DOMAttr& a) + { + entry e (static_cast<xercesc::DOMAttr*> ( + doc_.importNode ( + const_cast<xercesc::DOMAttr*> (&a), true))); + + std::pair<base_iterator, bool> r (s_.insert (e)); + + return std::pair<iterator, bool> (iterator (r.first), r.second); + } + + // Assumes ownership. + // + std::pair<iterator, bool> + insert (xercesc::DOMAttr* a) + { + assert (a->getOwnerDocument () == &doc_); + entry e (a); + std::pair<base_iterator, bool> r (s_.insert (e)); + + if (!r.second) + e.release (); // Detach the attribute of insert failed. + + return std::pair<iterator, bool> (iterator (r.first), r.second); + } + + // Makes a deep copy. + // + iterator + insert (iterator position, const xercesc::DOMAttr& a) + { + entry e (static_cast<xercesc::DOMAttr*> ( + doc_.importNode ( + const_cast<xercesc::DOMAttr*> (&a), true))); + + return iterator (s_.insert (position.base (), e)); + } + + // Assumes ownership. + // + iterator + insert (iterator position, xercesc::DOMAttr* a) + { + assert (a->getOwnerDocument () == &doc_); + entry e (a); + base_iterator r (s_.insert (position.base (), e)); + + if (r->get () != a) + e.release (); // Detach the attribute of insert failed. + + return iterator (r); + } + + template <typename I> + void + insert (const I& begin, const I& end) + { + for (I i (begin); i != end; ++i) + { + entry e (static_cast<xercesc::DOMAttr*> ( + doc_.importNode ( + const_cast<xercesc::DOMAttr*> (&(*i)), true))); + + s_.insert (e); + } + } + + public: + void + erase (iterator position) + { + s_.erase (position.base ()); + } + + size_type + erase (const std::basic_string<C>& name) + { + return s_.erase (entry (0, xml::string (name).c_str ())); + } + + size_type + erase (const std::basic_string<C>& namespace_, + const std::basic_string<C>& name) + { + return s_.erase (entry (xml::string (namespace_).c_str (), + xml::string (name).c_str ())); + } + + size_type + erase (const XMLCh* name) + { + return s_.erase (entry (0, name)); + } + + size_type + erase (const XMLCh* namespace_, const XMLCh* name) + { + return s_.erase (entry (namespace_, name)); + } + + void + erase (iterator begin, iterator end) + { + s_.erase (begin.base (), end.base ()); + } + + public: + size_type + count (const std::basic_string<C>& name) const + { + return s_.count (entry (0, xml::string (name).c_str ())); + } + + size_type + count (const std::basic_string<C>& namespace_, + const std::basic_string<C>& name) const + { + return s_.count (entry (xml::string (namespace_).c_str (), + xml::string (name).c_str ())); + } + + size_type + count (const XMLCh* name) const + { + return s_.count (entry (0, name)); + } + + size_type + count (const XMLCh* namespace_, const XMLCh* name) const + { + return s_.count (entry (namespace_, name)); + } + + // find + // + + iterator + find (const std::basic_string<C>& name) + { + return iterator (s_.find (entry (0, xml::string (name).c_str ()))); + } + + iterator + find (const std::basic_string<C>& namespace_, + const std::basic_string<C>& name) + { + return iterator ( + s_.find (entry (xml::string (namespace_).c_str (), + xml::string (name).c_str ()))); + } + + iterator + find (const XMLCh* name) + { + return iterator (s_.find (entry (0, name))); + } + + iterator + find (const XMLCh* namespace_, const XMLCh* name) + { + return iterator (s_.find (entry (namespace_, name))); + } + + const_iterator + find (const std::basic_string<C>& name) const + { + return const_iterator ( + s_.find (entry (0, xml::string (name).c_str ()))); + } + + const_iterator + find (const std::basic_string<C>& namespace_, + const std::basic_string<C>& name) const + { + return const_iterator ( + s_.find (entry (xml::string (namespace_).c_str (), + xml::string (name).c_str ()))); + } + + const_iterator + find (const XMLCh* name) const + { + return const_iterator (s_.find (entry (0, name))); + } + + const_iterator + find (const XMLCh* namespace_, const XMLCh* name) const + { + return const_iterator (s_.find (entry (namespace_, name))); + } + + public: + // Note that the DOMDocument object of the two sets being + // swapped should be the same. + // + void + swap (attribute_set& x) + { + assert (&doc_ == &x.doc_); + s_.swap (x.s_); + } + + private: + base_set s_; + xercesc::DOMDocument& doc_; + }; + + // Comparison operators. + // + + template <typename C> + inline bool + operator== (const attribute_set<C>& a, const attribute_set<C>& b) + { + if (a.size () != b.size ()) + return false; + + typename attribute_set<C>::const_iterator + ai (a.begin ()), ae (a.end ()), bi (b.begin ()); + + for (; ai != ae; ++ai, ++bi) + if (!ai->isEqualNode (&(*bi))) + return false; + + return true; + } + + template <typename C> + inline bool + operator!= (const attribute_set<C>& a, const attribute_set<C>& b) + { + return !(a == b); + } + } + } +} + +#endif // XSD_CXX_TREE_CONTAINERS_WILDCARD_HXX |