diff options
Diffstat (limited to 'xsd/libxsd/xsd/cxx/tree/elements.hxx')
-rw-r--r-- | xsd/libxsd/xsd/cxx/tree/elements.hxx | 596 |
1 files changed, 482 insertions, 114 deletions
diff --git a/xsd/libxsd/xsd/cxx/tree/elements.hxx b/xsd/libxsd/xsd/cxx/tree/elements.hxx index 403fdb3..a3bbea4 100644 --- a/xsd/libxsd/xsd/cxx/tree/elements.hxx +++ b/xsd/libxsd/xsd/cxx/tree/elements.hxx @@ -1,6 +1,5 @@ // file : xsd/cxx/tree/elements.hxx -// author : Boris Kolpackov <boris@codesynthesis.com> -// copyright : Copyright (c) 2005-2010 Code Synthesis Tools CC +// copyright : Copyright (c) 2005-2014 Code Synthesis Tools CC // license : GNU GPL v2 + exceptions; see accompanying LICENSE file /** @@ -17,25 +16,40 @@ #ifndef XSD_CXX_TREE_ELEMENTS_HXX #define XSD_CXX_TREE_ELEMENTS_HXX +#include <xsd/cxx/config.hxx> // XSD_AUTO_PTR, XSD_CXX11 + #include <map> #include <string> -#include <memory> // std::auto_ptr +#include <memory> // std::auto_ptr/unique_ptr +#include <cstddef> // std::size_t #include <istream> #include <sstream> #include <cassert> +#ifdef XSD_CXX11 +# include <utility> // std::move +#endif + #include <xercesc/dom/DOMNode.hpp> #include <xercesc/dom/DOMAttr.hpp> #include <xercesc/dom/DOMElement.hpp> #include <xercesc/dom/DOMDocument.hpp> #include <xercesc/dom/DOMNamedNodeMap.hpp> +#include <xercesc/util/XercesVersion.hpp> + #include <xsd/cxx/xml/elements.hxx> // xml::properties -#include <xsd/cxx/xml/dom/auto-ptr.hxx> // dom::auto_ptr +#include <xsd/cxx/xml/dom/auto-ptr.hxx> // dom::auto_ptr/unique_ptr +#include <xsd/cxx/xml/dom/wildcard-source.hxx> // dom::create_document() #include <xsd/cxx/tree/facet.hxx> #include <xsd/cxx/tree/exceptions.hxx> #include <xsd/cxx/tree/istream-fwd.hxx> +#include <xsd/cxx/tree/containers-wildcard.hxx> + +#if _XERCES_VERSION < 30000 +# error Xerces-C++ 2-series is not supported +#endif namespace xsd { @@ -77,7 +91,7 @@ namespace xsd * * This flag only makes sense together with the @c keep_dom * flag in the call to the %parsing function with the - * @c dom::auto_ptr<DOMDocument> argument. + * @c dom::auto_ptr/unique_ptr<DOMDocument> argument. * */ static const unsigned long own_dom = 0x00000200UL; @@ -89,6 +103,12 @@ namespace xsd static const unsigned long dont_validate = 0x00000400UL; /** + * @brief Extract XML content for anyType or anySimpleType. + * Normally you don't need to specify this flag explicitly. + */ + static const unsigned long extract_content = 0x00000800UL; + + /** * @brief Do not initialize the Xerces-C++ runtime. */ static const unsigned long dont_initialize = 0x00000001UL; @@ -179,7 +199,6 @@ namespace xsd unsigned long x_; }; - // Parsing properties. Refer to xsd/cxx/xml/elements.hxx for XML- // related properties. // @@ -188,6 +207,44 @@ namespace xsd { }; + /** + * @brief Content order sequence entry. + * + * @nosubgrouping + */ + struct content_order + { + /** + * @brief Initialize an instance with passed id and index. + * + * @param id Content id. + * @param index Content index in the corresponding sequence. + */ + content_order (std::size_t id, std::size_t index = 0) + : id (id), index (index) + { + } + + /** + * @brief Content id. + */ + std::size_t id; + + /** + * @brief Content index. + */ + std::size_t index; + }; + + bool + operator== (const content_order&, const content_order&); + + bool + operator!= (const content_order&, const content_order&); + + bool + operator< (const content_order&, const content_order&); + //@cond // DOM user data keys. @@ -202,12 +259,6 @@ namespace xsd typedef user_data_keys_template<0> user_data_keys; - // HP aCC3 complains about unresolved symbols without an explicit - // instantiation. - // -#if defined(__HP_aCC) && __HP_aCC <= 39999 - template struct user_data_keys_template<0>; -#endif // // struct identity @@ -284,10 +335,20 @@ namespace xsd /** * @brief Default constructor. */ - _type () - : container_ (0) - { - } + _type (); + + /** + * @brief Create an instance from a C string. + * + * @param s A string to initialize the instance with. + * + * Note that this constructor ignores the string and creates an + * empty anyType instance. In particular, it will not convert the + * string into DOM content. The purpose of such a strange constructor + * is to allow statically-initialized default values of anyType type. + */ + template <typename C> + _type (const C* s); public: /** @@ -339,7 +400,9 @@ namespace xsd * @param c A pointer to the object that will contain the new * instance. */ - _type (const xercesc::DOMElement& e, flags f = 0, container* c = 0); + _type (const xercesc::DOMElement& e, + flags f = flags::extract_content, + container* c = 0); /** * @brief Create an instance from a DOM Attribute. @@ -377,10 +440,150 @@ namespace xsd type& operator= (const type& x) { - while (&x == 0) /* unused */; + if (this != &x) + { + if (x.content_.get () == 0) + content_.reset (); + else + content_ = x.content_->clone (); + + // Drop DOM association. + // + dom_info_.reset (); + } + return *this; } + // anyType content API. + // + public: + typedef element_optional dom_content_optional; + + /** + * @brief Return a read-only (constant) reference to the anyType + * DOM content. + * + * @return A constant reference to the optional container. + * + * The DOM content is returned as an optional element container, + * the same container as used for optional element wildcards. + */ + const dom_content_optional& + dom_content () const; + + /** + * @brief Return a read-write reference to the anyType DOM content. + * + * @return A reference to the optional container. + * + * The DOM content is returned as an optional element container, + * the same container as used for optional element wildcards. + */ + dom_content_optional& + dom_content (); + + /** + * @brief Set the anyType DOM content. + * + * @param e A new element to set. + * + * This function makes a copy of its argument and sets it as the + * new DOM content. + */ + void + dom_content (const xercesc::DOMElement& e); + + /** + * @brief Set the anyType DOM content. + * + * @param e A new element to use. + * + * This function will use the passed element directly instead + * of making a copy. For this to work the element should belong + * to the DOM document associated with this anyType instance. + * + * @see dom_content_document + */ + void + dom_content (xercesc::DOMElement* e); + + /** + * @brief Set the anyType DOM content. + * + * @param d An optional container with the new element to set. + * + * If the element is present in @a d then this function makes a + * copy of this element and sets it as the new wildcard content. + * Otherwise the element container is set the 'not present' state. + */ + void + dom_content (const dom_content_optional& d); + + /** + * @brief Return a read-only (constant) reference to the DOM + * document associated with this anyType instance. + * + * @return A constant reference to the DOM document. + * + * The DOM document returned by this function is used to store + * the raw XML content corresponding to the anyType instance. + */ + const xercesc::DOMDocument& + dom_content_document () const; + + /** + * @brief Return a read-write reference to the DOM document + * associated with this anyType instance. + * + * @return A reference to the DOM document. + * + * The DOM document returned by this function is used to store + * the raw XML content corresponding to the anyType instance. + */ + xercesc::DOMDocument& + dom_content_document (); + + /** + * @brief Check for absence of DOM (anyType) and text (anySimpleType) + * content. + * + * @return True if there is no content and false otherwise. + * + * This is an optimization function that allows us to check for the + * lack of content without actually creating its empty representation + * (that is, empty DOM document for DOM or empty string for text). + */ + bool + null_content () const; + + // + // + public: + /** + * @brief Comparison operator. It uses DOM (anyType) or text + * (anySimpleType) content if present. If the content is missing + * then the types are assumed unequal. + * + * @return True if the instances are equal, false otherwise. + */ + friend bool + operator== (const type& x, const type& y) + { + return x.content_.get () != 0 && + x.content_->compare (y.content_.get ()); + } + + /** + * @brief Comparison operator. It uses DOM (anyType) or text + * (anySimpleType) content if present. If the content is missing + * then the types are assumed unequal. + * + * @return True if the instances are not equal, false otherwise. + */ + friend bool + operator!= (const type& x, const type& y) {return !(x == y);} + // Container API. // public: @@ -429,7 +632,7 @@ namespace xsd dr = c; } - std::auto_ptr<map>& m (dr ? dr->map_ : map_); + XSD_AUTO_PTR<map>& m (dr ? dr->map_ : map_); if (container_ == 0) { @@ -440,11 +643,16 @@ namespace xsd if (m.get () != 0) { m->insert (map_->begin (), map_->end ()); - std::auto_ptr<map> tmp (0); - map_ = tmp; + map_.reset (); } else + { +#ifdef XSD_CXX11 + m = std::move (map_); +#else m = map_; +#endif + } } } else @@ -466,10 +674,7 @@ namespace xsd // Part of our subtree. // if (m.get () == 0) - { - std::auto_ptr<map> tmp (new map); - m = tmp; - } + m.reset (new map); m->insert (*i); sr->map_->erase (i++); @@ -548,7 +753,7 @@ namespace xsd * @brief Exception indicating that a DOM node cannot be associated * with an object model node. */ - class bad_dom_node_type: public std::exception //@@ Inherit exception. + class bad_dom_node_type: public std::exception //@@ Inherit exception<C>. { public: /** @@ -584,37 +789,31 @@ namespace xsd { if (container_ != 0) { - // @@ Should be a throw. - // assert (_root ()->_node () != 0); assert (_root ()->_node ()->getOwnerDocument () == n->getOwnerDocument ()); } - std::auto_ptr<dom_info> r ( + dom_info_ = dom_info_factory::create ( *static_cast<xercesc::DOMElement*> (n), *this, - container_ == 0)); + container_ == 0); - dom_info_ = r; break; } case xercesc::DOMNode::ATTRIBUTE_NODE: { - //@@ Should be a throw. - // assert (container_ != 0); assert (_root ()->_node () != 0); assert (_root ()->_node ()->getOwnerDocument () == n->getOwnerDocument ()); - std::auto_ptr<dom_info> r ( + dom_info_ = dom_info_factory::create ( *static_cast<xercesc::DOMAttr*> (n), - *this)); + *this); - dom_info_ = r; break; } default: @@ -628,26 +827,23 @@ namespace xsd //@cond void - _register_id (const identity& id, type* t) + _register_id (const identity& i, type* t) { // We should be the root. // assert (container_ == 0); if (map_.get () == 0) - { - std::auto_ptr<map> tmp (new map); - map_ = tmp; - } + map_.reset (new map); if (!map_->insert ( - std::pair<const identity*, type*> (&id, t)).second) + std::pair<const identity*, type*> (&i, t)).second) { - id.throw_duplicate_id (); + i.throw_duplicate_id (); } } - //@@ Does not inherit from exception. + //@@ Does not inherit from exception<C>. // struct not_registered: std::exception { @@ -691,15 +887,11 @@ namespace xsd struct dom_info { virtual - ~dom_info () - { - } + ~dom_info () {} - dom_info () - { - } + dom_info () {} - virtual std::auto_ptr<dom_info> + virtual XSD_AUTO_PTR<dom_info> clone (type& tree_node, container*) const = 0; virtual xercesc::DOMNode* @@ -707,41 +899,41 @@ namespace xsd private: dom_info (const dom_info&); - - dom_info& - operator= (const dom_info&); + dom_info& operator= (const dom_info&); }; - struct dom_element_info: public dom_info { dom_element_info (xercesc::DOMElement& e, type& n, bool root) - : doc_ (0), e_ (e) + : e_ (e) { e_.setUserData (user_data_keys::node, &n, 0); if (root) { - // The caller should have associated a dom::auto_ptr object - // that owns this document with the document node using the - // xml_schema::dom::tree_node_key key. + // The caller should have associated a dom::auto/unique_ptr + // object that owns this document with the document node + // using the xml_schema::dom::tree_node_key key. // - xml::dom::auto_ptr<xercesc::DOMDocument>* pd ( - reinterpret_cast<xml::dom::auto_ptr<xercesc::DOMDocument>*> ( + XSD_DOM_AUTO_PTR<xercesc::DOMDocument>* pd ( + reinterpret_cast<XSD_DOM_AUTO_PTR<xercesc::DOMDocument>*> ( e.getOwnerDocument ()->getUserData (user_data_keys::node))); assert (pd != 0); assert (pd->get () == e.getOwnerDocument ()); - doc_ = *pd; // Transfer ownership. + // Transfer ownership. +#ifdef XSD_CXX11 + doc_ = std::move (*pd); +#else + doc_ = *pd; +#endif } } - virtual std::auto_ptr<dom_info> + virtual XSD_AUTO_PTR<dom_info> clone (type& tree_node, container* c) const { - using std::auto_ptr; - // Check if we are a document root. // if (c == 0) @@ -749,11 +941,10 @@ namespace xsd // We preserver DOM associations only in complete // copies from root. // - if (doc_.get () == 0) - return auto_ptr<dom_info> (0); - - return auto_ptr<dom_info> ( - new dom_element_info (*doc_, tree_node)); + return XSD_AUTO_PTR<dom_info> ( + doc_.get () == 0 + ? 0 + : new dom_element_info (*doc_, tree_node)); } // Check if our container does not have DOM association (e.g., @@ -764,8 +955,7 @@ namespace xsd DOMNode* cn (c->_node ()); if (cn == 0) - return auto_ptr<dom_info> (0); - + return XSD_AUTO_PTR<dom_info> (); // Now we are going to find the corresponding element in // the new tree. @@ -797,7 +987,7 @@ namespace xsd assert (dn->getNodeType () == DOMNode::ELEMENT_NODE); - return auto_ptr<dom_info> ( + return XSD_AUTO_PTR<dom_info> ( new dom_element_info (static_cast<DOMElement&> (*dn), tree_node, false)); @@ -820,7 +1010,7 @@ namespace xsd } private: - xml::dom::auto_ptr<xercesc::DOMDocument> doc_; + XSD_DOM_AUTO_PTR<xercesc::DOMDocument> doc_; xercesc::DOMElement& e_; }; @@ -833,11 +1023,9 @@ namespace xsd a_.setUserData (user_data_keys::node, &n, 0); } - virtual std::auto_ptr<dom_info> + virtual XSD_AUTO_PTR<dom_info> clone (type& tree_node, container* c) const { - using std::auto_ptr; - // Check if we are a document root. // if (c == 0) @@ -845,7 +1033,7 @@ namespace xsd // We preserver DOM associations only in complete // copies from root. // - return auto_ptr<dom_info> (0); + return XSD_AUTO_PTR<dom_info> (); } // Check if our container does not have DOM association (e.g., @@ -856,7 +1044,7 @@ namespace xsd DOMNode* cn (c->_node ()); if (cn == 0) - return auto_ptr<dom_info> (0); + return XSD_AUTO_PTR<dom_info> (); // We are going to find the corresponding attribute in // the new tree. @@ -883,7 +1071,7 @@ namespace xsd DOMNode& n (*cn->getAttributes ()->item (i)); assert (n.getNodeType () == DOMNode::ATTRIBUTE_NODE); - return auto_ptr<dom_info> ( + return XSD_AUTO_PTR<dom_info> ( new dom_attribute_info (static_cast<DOMAttr&> (n), tree_node)); } @@ -904,18 +1092,18 @@ namespace xsd struct dom_info_factory { - static std::auto_ptr<dom_info> + static XSD_AUTO_PTR<dom_info> create (const xercesc::DOMElement& e, type& n, bool root) { - return std::auto_ptr<dom_info> ( + return XSD_AUTO_PTR<dom_info> ( new dom_element_info ( const_cast<xercesc::DOMElement&> (e), n, root)); } - static std::auto_ptr<dom_info> + static XSD_AUTO_PTR<dom_info> create (const xercesc::DOMAttr& a, type& n) { - return std::auto_ptr<dom_info> ( + return XSD_AUTO_PTR<dom_info> ( new dom_attribute_info ( const_cast<xercesc::DOMAttr&> (a), n)); } @@ -923,7 +1111,7 @@ namespace xsd //@endcond - std::auto_ptr<dom_info> dom_info_; + XSD_AUTO_PTR<dom_info> dom_info_; // ID/IDREF map. @@ -946,23 +1134,77 @@ namespace xsd std::map<const identity*, type*, identity_comparator> map; - std::auto_ptr<map> map_; + XSD_AUTO_PTR<map> map_; - private: - container* container_; - }; + // anyType and anySimpleType content. + // + protected: - inline _type:: - _type (const type& x, flags, container* c) - : container_ (c) - { - if (x.dom_info_.get ()) + //@cond + + struct content_type { - std::auto_ptr<dom_info> r (x.dom_info_->clone (*this, c)); - dom_info_ = r; - } - } + virtual + ~content_type () {} + + content_type () {} + virtual XSD_AUTO_PTR<content_type> + clone () const = 0; + + virtual bool + compare (const content_type*) const = 0; + + private: + content_type (const content_type&); + content_type& operator= (const content_type&); + }; + + struct dom_content_type: content_type + { + dom_content_type () + : doc (xml::dom::create_document<char> ()), dom (*doc) {} + + explicit + dom_content_type (const xercesc::DOMElement& e) + : doc (xml::dom::create_document<char> ()), dom (e, *doc) {} + + explicit + dom_content_type (xercesc::DOMElement* e) + : doc (xml::dom::create_document<char> ()), dom (e, *doc) {} + + explicit + dom_content_type (const dom_content_optional& d) + : doc (xml::dom::create_document<char> ()), dom (d, *doc) {} + + virtual XSD_AUTO_PTR<content_type> + clone () const + { + return XSD_AUTO_PTR<content_type> (new dom_content_type (dom)); + } + + virtual bool + compare (const content_type* c) const + { + if (const dom_content_type* dc = + dynamic_cast<const dom_content_type*> (c)) + return dom == dc->dom; + + return false; + } + + public: + XSD_DOM_AUTO_PTR<xercesc::DOMDocument> doc; + dom_content_optional dom; + }; + + //@endcond + + mutable XSD_AUTO_PTR<content_type> content_; + + private: + container* container_; + }; /** * @brief Class corresponding to the XML Schema anySimpleType built-in @@ -970,7 +1212,7 @@ namespace xsd * * @nosubgrouping */ - template <typename B> + template <typename C, typename B> class simple_type: public B { public: @@ -985,13 +1227,19 @@ namespace xsd simple_type (); /** - * @brief Create an instance from a string. + * @brief Create an instance from a C string. * * @param s A string to initialize the instance with. */ - template <typename C> simple_type (const C* s); + /** + * @brief Create an instance from a string. + * + * @param s A string to initialize the instance with. + */ + simple_type (const std::basic_string<C>& s); + public: /** * @brief Copy constructor. @@ -1029,7 +1277,9 @@ namespace xsd * instance. */ template <typename S> - simple_type (istream<S>& s, flags f = 0, container* c = 0); + simple_type (istream<S>& s, + flags f = flags::extract_content, + container* c = 0); /** * @brief Create an instance from a DOM element. @@ -1040,7 +1290,7 @@ namespace xsd * instance. */ simple_type (const xercesc::DOMElement& e, - flags f = 0, + flags f = flags::extract_content, container* c = 0); /** @@ -1052,7 +1302,7 @@ namespace xsd * instance. */ simple_type (const xercesc::DOMAttr& a, - flags f = 0, + flags f = flags::extract_content, container* c = 0); /** @@ -1064,12 +1314,82 @@ namespace xsd * @param c A pointer to the object that will contain the new * instance. */ - template <typename C> simple_type (const std::basic_string<C>& s, const xercesc::DOMElement* e, - flags f = 0, + flags f = flags::extract_content, container* c = 0); //@} + + // anySimpleType content API. + // + public: + /** + * @brief Return a read-only (constant) reference to the anySimpleType + * text content. + * + * @return A constant reference to the text string. + */ + const std::basic_string<C>& + text_content () const; + + /** + * @brief Return a read-write reference to the anySimpleType text + * content. + * + * @return A reference to the text string. + */ + std::basic_string<C>& + text_content (); + + /** + * @brief Set the anySimpleType text content. + * + * @param e A new text string to set. + */ + void + text_content (const std::basic_string<C>& t); + + protected: + //@cond + + typedef typename B::content_type content_type; + + struct text_content_type: content_type + { + text_content_type () {} + + explicit + text_content_type (const std::basic_string<C>& t): text (t) {} + + explicit + text_content_type (const C* t): text (t) {} + + virtual XSD_AUTO_PTR<content_type> + clone () const + { + return XSD_AUTO_PTR<content_type> (new text_content_type (text)); + } + + virtual bool + compare (const content_type* c) const + { + if (const text_content_type* tc = + dynamic_cast<const text_content_type*> (c)) + return text == tc->text; + + return false; + } + + public: + // It would have been more elegant to store text content as DOMText. + // However, that would require Xerces-C++ initialization. Also + // having a separate DOMDocument for each text node seems like + // an overkill. + // + std::basic_string<C> text; + }; + + //@endcond }; @@ -1168,28 +1488,77 @@ namespace xsd { typedef T type; - static std::auto_ptr<T> + static XSD_AUTO_PTR<T> create (const xercesc::DOMElement& e, flags f, container* c) { - return std::auto_ptr<T> (new T (e, f, c)); + return XSD_AUTO_PTR<T> (new T (e, f, c)); } - static std::auto_ptr<T> + static XSD_AUTO_PTR<T> create (const xercesc::DOMAttr& a, flags f, container* c) { - return std::auto_ptr<T> (new T (a, f, c)); + return XSD_AUTO_PTR<T> (new T (a, f, c)); } - static std::auto_ptr<T> + static XSD_AUTO_PTR<T> create (const std::basic_string<C>& s, const xercesc::DOMElement* e, flags f, container* c) { - return std::auto_ptr<T> (new T (s, e, f, c)); + return XSD_AUTO_PTR<T> (new T (s, e, f, c)); + } + + // For now for istream we only go through traits for non- + // fundamental types. + // + template <typename S> + static XSD_AUTO_PTR<T> + create (istream<S>& s, flags f, container* c) + { + return XSD_AUTO_PTR<T> (new T (s, f, c)); } }; + template <typename B, + typename C, + schema_type::value ST> + struct traits<simple_type<C, B>, C, ST> + { + typedef simple_type<C, B> type; + + static XSD_AUTO_PTR<type> + create (const xercesc::DOMElement& e, flags f, container* c) + { + return XSD_AUTO_PTR<type> ( + new type (e, f | flags::extract_content, c)); + } + + static XSD_AUTO_PTR<type> + create (const xercesc::DOMAttr& a, flags f, container* c) + { + return XSD_AUTO_PTR<type> ( + new type (a, f | flags::extract_content, c)); + } + + static XSD_AUTO_PTR<type> + create (const std::basic_string<C>& s, + const xercesc::DOMElement* e, + flags f, + container* c) + { + return XSD_AUTO_PTR<type> ( + new type (s, e, f | flags::extract_content, c)); + } + + template <typename S> + static XSD_AUTO_PTR<type> + create (istream<S>& s, flags f, container* c) + { + return XSD_AUTO_PTR<type> ( + new type (s, f | flags::extract_content, c)); + } + }; //@endcond @@ -1352,8 +1721,7 @@ namespace xsd } // The following extra conversion operators causes problems on - // some compilers (notably VC 7.1 and 9.0) and are disabled by - // default. + // some compilers (notably VC 9.0) and are disabled by default. // #ifdef XSD_TREE_EXTRA_FUND_CONV /** |