// file : xsd/cxx/tree/containers-wildcard.hxx // license : GNU GPL v2 + exceptions; see accompanying LICENSE file #ifndef XSD_CXX_TREE_CONTAINERS_WILDCARD_HXX #define XSD_CXX_TREE_CONTAINERS_WILDCARD_HXX #include #include #include #include #include #include #include #include namespace xsd { namespace cxx { namespace tree { // one (for internal use only) // class element_one { public: typedef xercesc::DOMElement value_type; ~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 ( doc_.importNode (const_cast (&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: typedef xercesc::DOMElement value_type; ~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 ( doc_.importNode (const_cast (&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 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 iterator; typedef iterator_adapter const_iterator; typedef iterator_adapter reverse_iterator; typedef iterator_adapter 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 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 ( 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 ( 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 ( doc_.importNode ( const_cast (&x), true))); *i = p; } } template 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 ( doc_.importNode ( const_cast (&(*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 ( doc_.importNode ( const_cast (&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 ( doc_.importNode ( const_cast (&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 ( doc_.importNode ( const_cast (&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 ( doc_.importNode ( const_cast (&x), true))); *(--i) = r; } } template 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 ( 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) < 0); } }; typedef std::set base_set; typedef base_set::iterator base_iterator; typedef base_set::const_iterator base_const_iterator; }; template 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 iterator; typedef iterator_adapter const_iterator; typedef iterator_adapter reverse_iterator; typedef iterator_adapter 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 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 insert (const xercesc::DOMAttr& a) { entry e (static_cast ( doc_.importNode ( const_cast (&a), true))); std::pair r (s_.insert (e)); return std::pair (iterator (r.first), r.second); } // Assumes ownership. // std::pair insert (xercesc::DOMAttr* a) { assert (a->getOwnerDocument () == &doc_); entry e (a); std::pair r (s_.insert (e)); if (!r.second) e.release (); // Detach the attribute of insert failed. return std::pair (iterator (r.first), r.second); } // Makes a deep copy. // iterator insert (iterator position, const xercesc::DOMAttr& a) { entry e (static_cast ( doc_.importNode ( const_cast (&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 void insert (const I& begin, const I& end) { for (I i (begin); i != end; ++i) { entry e (static_cast ( doc_.importNode ( const_cast (&(*i)), true))); s_.insert (e); } } public: void erase (iterator position) { s_.erase (position.base ()); } size_type erase (const std::basic_string& name) { return s_.erase (entry (0, xml::string (name).c_str ())); } size_type erase (const std::basic_string& namespace_, const std::basic_string& 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& name) const { return s_.count (entry (0, xml::string (name).c_str ())); } size_type count (const std::basic_string& namespace_, const std::basic_string& 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& name) { return iterator (s_.find (entry (0, xml::string (name).c_str ()))); } iterator find (const std::basic_string& namespace_, const std::basic_string& 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& name) const { return const_iterator ( s_.find (entry (0, xml::string (name).c_str ()))); } const_iterator find (const std::basic_string& namespace_, const std::basic_string& 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 inline bool operator== (const attribute_set& a, const attribute_set& b) { if (a.size () != b.size ()) return false; typename attribute_set::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 inline bool operator!= (const attribute_set& a, const attribute_set& b) { return !(a == b); } } } } #endif // XSD_CXX_TREE_CONTAINERS_WILDCARD_HXX