From 1a4099b78717b16f632b0e7e0980a27811221e52 Mon Sep 17 00:00:00 2001 From: Boris Kolpackov Date: Thu, 3 Jul 2014 09:57:09 +0200 Subject: Implement anyType and anySimpleType content representation anyType as a DOM fragment, similar to wildcards. anySimpleType as a text string. --- NEWS | 8 + doc/cxx/tree/manual/index.xhtml | 94 ++++++- libxsd/xsd/cxx/tree/comparison-map.txx | 19 +- libxsd/xsd/cxx/tree/containers-wildcard.hxx | 2 +- libxsd/xsd/cxx/tree/containers.hxx | 256 +---------------- libxsd/xsd/cxx/tree/elements.hxx | 386 +++++++++++++++++++++++--- libxsd/xsd/cxx/tree/elements.ixx | 213 +++++++++++++- libxsd/xsd/cxx/tree/elements.txx | 8 +- libxsd/xsd/cxx/tree/iterator-adapter.hxx | 270 ++++++++++++++++++ libxsd/xsd/cxx/tree/list.hxx | 2 +- libxsd/xsd/cxx/tree/parsing.txx | 62 +++-- libxsd/xsd/cxx/tree/serialization.txx | 41 ++- libxsd/xsd/cxx/tree/std-ostream-map.txx | 2 +- libxsd/xsd/cxx/tree/std-ostream-operators.hxx | 6 +- libxsd/xsd/cxx/tree/stream-extraction-map.txx | 2 +- libxsd/xsd/cxx/tree/stream-extraction.hxx | 16 +- libxsd/xsd/cxx/tree/stream-insertion-map.txx | 2 +- libxsd/xsd/cxx/tree/stream-insertion.hxx | 8 +- libxsd/xsd/cxx/tree/type-factory-map.txx | 2 +- libxsd/xsd/cxx/tree/type-serializer-map.txx | 2 +- libxsd/xsd/cxx/tree/types.hxx | 166 +++++++++++ libxsd/xsd/cxx/xml/string.hxx | 17 +- tests/cxx/tree/any-type/driver.cxx | 145 ++++++++++ tests/cxx/tree/any-type/makefile | 87 ++++++ tests/cxx/tree/any-type/output | 73 +++++ tests/cxx/tree/any-type/test.xml | 26 ++ tests/cxx/tree/any-type/test.xsd | 19 ++ tests/cxx/tree/binary/cdr/driver.cxx | 8 + tests/cxx/tree/binary/cdr/makefile | 2 +- tests/cxx/tree/binary/cdr/test.xml | 4 +- tests/cxx/tree/binary/cdr/test.xsd | 3 + tests/cxx/tree/binary/polymorphic/makefile | 3 +- tests/cxx/tree/binary/xdr/driver.cxx | 8 + tests/cxx/tree/binary/xdr/makefile | 3 +- tests/cxx/tree/binary/xdr/test.xml | 4 +- tests/cxx/tree/binary/xdr/test.xsd | 3 + tests/cxx/tree/compilation/driver.cxx | 2 +- tests/cxx/tree/makefile | 1 + xsd/cxx/tree/fundamental-header.hxx | 2 +- xsd/cxx/tree/options.cli | 7 + xsd/cxx/tree/stream-extraction-source.cxx | 22 +- xsd/cxx/tree/tree-header.cxx | 16 ++ xsd/cxx/tree/tree-inline.cxx | 22 ++ xsd/cxx/tree/tree-source.cxx | 8 +- 44 files changed, 1663 insertions(+), 389 deletions(-) create mode 100644 libxsd/xsd/cxx/tree/iterator-adapter.hxx create mode 100644 tests/cxx/tree/any-type/driver.cxx create mode 100644 tests/cxx/tree/any-type/makefile create mode 100644 tests/cxx/tree/any-type/output create mode 100644 tests/cxx/tree/any-type/test.xml create mode 100644 tests/cxx/tree/any-type/test.xsd diff --git a/NEWS b/NEWS index bb220b9..0145a07 100644 --- a/NEWS +++ b/NEWS @@ -38,6 +38,14 @@ C++/Tree to Section 2.13, "Mapping for Mixed Content Models" in the C++/Tree Mapping User Manual. + * xml_schema::typecan represent anyType content as a DOM fragment, similar + to wildcards. For more information, refer to Section 2.5.2, "Mapping for + anyType" in the C++/Tree Mapping User Manual. + + * xml_schema::simple_type can represent anySimpleType content as a text + string. For more information, refer to Section 2.5.3, "Mapping for + anySimpleType" in the C++/Tree Mapping User Manual. + * New option, --suppress-assignment, suppress the generation of copy assignment operators for complex types. If this option is specified, the copy assignment operators for such types are declared private diff --git a/doc/cxx/tree/manual/index.xhtml b/doc/cxx/tree/manual/index.xhtml index 052f2b3..235c33c 100644 --- a/doc/cxx/tree/manual/index.xhtml +++ b/doc/cxx/tree/manual/index.xhtml @@ -1214,18 +1214,44 @@ public: virtual ~type (); -public: type (); type (const type&); -public: type& operator= (const type&); -public: virtual type* _clone () const; + // anyType DOM content. + // +public: + typedef element_optional dom_content_optional; + + const dom_content_optional& + dom_content () const; + + dom_content_optional& + dom_content (); + + void + dom_content (const xercesc::DOMElement&); + + void + dom_content (xercesc::DOMElement*); + + void + dom_content (const dom_content_optional&); + + const xercesc::DOMDocument& + dom_content_document () const; + + xercesc::DOMDocument& + dom_content_document (); + + bool + null_content () const; + // DOM association. // public: @@ -1237,7 +1263,44 @@ public: }; -

For more information about DOM association refer to +

When xml_schema::type is used to create an instance + (as opposed to being a base of a derived type), it represents + the XML Schema anyType type. anyType + allows any attributes and any content in any order. In the + C++/Tree mapping this content can be represented as a DOM + fragment, similar to XML Schema wildcards (Section + 2.12, "Mapping for any and + anyAttribute").

+ +

To enable automatic extraction of anyType content + during parsing, the --generate-any-type option must be + specified. Because the DOM API is used to access such content, the + Xerces-C++ runtime should be initialized by the application prior to + parsing and should remain initialized for the lifetime of objects + with the DOM content. For more information on the Xerces-C++ runtime + initialization see Section 3.1, "Initializing the + Xerces-C++ Runtime".

+ +

The DOM content is stored as the optional DOM element container + and the DOM content accessors and modifiers presented above are + identical to those generated for an optional element wildcard. + Refer to Section 2.12.2, "Mapping for any + with the Optional Cardinality Class" for details on their + semantics.

+ +

The dom_content_document() function returns the + DOM document used to store the raw XML content corresponding + to the anyType instance. It is equivalent to the + dom_document() function generated for types + with wildcards.

+ +

The null_content() accessor 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 + anyType or empty string for anySimpleType + (see the following section for details on anySimpleType).

+ +

For more information on DOM association refer to Section 5.1, "DOM Association".

2.5.3 Mapping for anySimpleType

@@ -1250,18 +1313,37 @@ class simple_type: public type { public: simple_type (); + simple_type (const C*); + simple_type (const std::basic_string<C>&); + simple_type (const simple_type&); -public: simple_type& operator= (const simple_type&); -public: virtual simple_type* _clone () const; + + // anySimpleType text content. + // +public: + const std::basic_string<C>& + text_content () const; + + std::basic_string<C>& + text_content (); + + void + text_content (const std::basic_string<C>&); }; +

When xml_schema::simple_type is used to create an instance + (as opposed to being a base of a derived type), it represents + the XML Schema anySimpleType type. anySimpleType + allows any simple content. In the C++/Tree mapping this content can + be represented as a string and accessed or modified with the + text_content() functions shown above.

2.5.4 Mapping for QName

diff --git a/libxsd/xsd/cxx/tree/comparison-map.txx b/libxsd/xsd/cxx/tree/comparison-map.txx index e996aec..af23d64 100644 --- a/libxsd/xsd/cxx/tree/comparison-map.txx +++ b/libxsd/xsd/cxx/tree/comparison-map.txx @@ -19,18 +19,17 @@ namespace xsd // anyType and anySimpleType. // - //register_type ( - // typeid (type), - // &comparator_impl, - // false); - - typedef simple_type simple_type; + register_type ( + typeid (type), + &comparator_impl, + false); - //register_type ( - // typeid (simple_type), - // &comparator_impl, - // false); + typedef simple_type simple_type; + register_type ( + typeid (simple_type), + &comparator_impl, + false); // Strings // diff --git a/libxsd/xsd/cxx/tree/containers-wildcard.hxx b/libxsd/xsd/cxx/tree/containers-wildcard.hxx index f4d3be2..549df73 100644 --- a/libxsd/xsd/cxx/tree/containers-wildcard.hxx +++ b/libxsd/xsd/cxx/tree/containers-wildcard.hxx @@ -15,7 +15,7 @@ #include -#include // iterator_adapter +#include namespace xsd { diff --git a/libxsd/xsd/cxx/tree/containers.hxx b/libxsd/xsd/cxx/tree/containers.hxx index c89218f..cafd79d 100644 --- a/libxsd/xsd/cxx/tree/containers.hxx +++ b/libxsd/xsd/cxx/tree/containers.hxx @@ -5,17 +5,15 @@ #ifndef XSD_CXX_TREE_CONTAINERS_HXX #define XSD_CXX_TREE_CONTAINERS_HXX -#include // std::ptrdiff_t -#include #include #include // std::auto_ptr/unique_ptr -#include // std::iterator_traits #include // std::equal, std::lexicographical_compare #include #include // XSD_AUTO_PTR #include +#include namespace xsd { @@ -515,7 +513,7 @@ namespace xsd return !(a < b); } - // Provide an ostream insertion opretaor to prevent confusion from + // Provide an ostream insertion operator to prevent confusion from // the implicit bool conversion. // template @@ -528,256 +526,6 @@ namespace xsd template ::r> class sequence; - // Sun CC's does not have iterator_traits. To overcome - // this, we will wrap std::iterator_traits into our own and also - // specialize it for pointer types. Since Sun CC uses pointer - // for vector::iterator, it will use the specialization and won't - // notice the std::iterator_traits. - // -#ifndef _RWSTD_NO_CLASS_PARTIAL_SPEC - template - struct iterator_traits - { - typedef - typename std::iterator_traits::iterator_category - iterator_category; - - typedef - typename std::iterator_traits::value_type - value_type; - - typedef - typename std::iterator_traits::difference_type - difference_type; - }; -#else - // The Pointer specialization does not work for reverse and - // set iterators. But these iterators are user-dfined types - // and have suitable typedefs that we can use. - // - template - struct iterator_traits - { - typedef typename I::iterator_category iterator_category; - typedef typename I::value_type value_type; - typedef typename I::difference_type difference_type; - }; - - template - struct iterator_traits - { - typedef std::random_access_iterator_tag iterator_category; - typedef T value_type; - typedef std::ptrdiff_t difference_type; - }; -#endif - - // Iterator adapter for complex types. It expects I to point to - // a smart pointer-like object that has operator*() that returns - // a refernce to a type static_cast'able to T and get() that - // returns a pointer to a type static_cast'able to T. - // - - template - struct iterator_adapter - { - typedef T value_type; - typedef value_type& reference; - typedef value_type* pointer; - - typedef - typename iterator_traits::iterator_category - iterator_category; - - typedef - typename iterator_traits::difference_type - difference_type; - - - public: - iterator_adapter () - : i_ () // i_ can be of a pointer type. - { - } - - // Allow iterator to const_iterator conversion. - // - template - iterator_adapter (const iterator_adapter& j) - : i_ (j.base ()) - { - } - - explicit - iterator_adapter (const I& i) - : i_ (i) - { - } - - public: - // Forward iterator requirements. - // - reference - operator* () const - { - return static_cast (**i_); - } - - pointer - operator-> () const - { - return static_cast (i_->get ()); - } - - iterator_adapter& - operator++ () - { - ++i_; - return *this; - } - - iterator_adapter - operator++ (int) - { - iterator_adapter r (*this); - ++i_; - return r; - } - - // Bidirectional iterator requirements. - // - iterator_adapter& - operator-- () - { - --i_; - return *this; - } - - iterator_adapter - operator-- (int) - { - iterator_adapter r (*this); - --i_; - return r; - } - - // Random access iterator requirements. - // - reference - operator[] (difference_type n) const - { - return static_cast (*(i_[n])); - } - - iterator_adapter& - operator+= (difference_type n) - { - i_ += n; - return *this; - } - - iterator_adapter - operator+ (difference_type n) const - { - return iterator_adapter (i_ + n); - } - - iterator_adapter& - operator-= (difference_type n) - { - i_ -= n; - return *this; - } - - iterator_adapter - operator- (difference_type n) const - { - return iterator_adapter (i_ - n); - } - - public: - const I& - base () const - { - return i_; - } - - private: - I i_; - }; - - // Note: We use different types for left- and right-hand-side - // arguments to allow comparison between iterator and const_iterator. - // - - // Forward iterator requirements. - // - template - inline bool - operator== (const iterator_adapter& i, - const iterator_adapter& j) - { - return i.base () == j.base (); - } - - template - inline bool - operator!= (const iterator_adapter& i, - const iterator_adapter& j) - { - return i.base () != j.base (); - } - - // Random access iterator requirements - // - template - inline bool - operator< (const iterator_adapter& i, - const iterator_adapter& j) - { - return i.base () < j.base (); - } - - template - inline bool - operator> (const iterator_adapter& i, - const iterator_adapter& j) - { - return i.base () > j.base (); - } - - template - inline bool - operator<= (const iterator_adapter& i, - const iterator_adapter& j) - { - return i.base () <= j.base (); - } - - template - inline bool - operator>= (const iterator_adapter& i, - const iterator_adapter& j) - { - return i.base () >= j.base (); - } - - template - inline typename iterator_adapter::difference_type - operator- (const iterator_adapter& i, - const iterator_adapter& j) - { - return i.base () - j.base (); - } - - template - inline iterator_adapter - operator+ (typename iterator_adapter::difference_type n, - const iterator_adapter& i) - { - return iterator_adapter (i.base () + n); - } - // // class sequence_common diff --git a/libxsd/xsd/cxx/tree/elements.hxx b/libxsd/xsd/cxx/tree/elements.hxx index 89be61e..ee32a62 100644 --- a/libxsd/xsd/cxx/tree/elements.hxx +++ b/libxsd/xsd/cxx/tree/elements.hxx @@ -40,10 +40,12 @@ #include // xml::properties #include // dom::auto_ptr/unique_ptr +#include // dom::create_document() #include #include #include +#include #if _XERCES_VERSION < 30000 # error Xerces-C++ 2-series is not supported @@ -101,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; @@ -330,9 +338,14 @@ namespace xsd _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. + * + * 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 _type (const C* s); @@ -387,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. @@ -427,6 +442,11 @@ namespace xsd { if (this != &x) { + if (x.content_.get () == 0) + content_.reset (); + else + content_ = x.content_->clone (); + // Drop DOM association. // dom_info_.reset (); @@ -435,6 +455,135 @@ namespace xsd 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: @@ -738,13 +887,9 @@ namespace xsd struct dom_info { virtual - ~dom_info () - { - } + ~dom_info () {} - dom_info () - { - } + dom_info () {} virtual XSD_AUTO_PTR clone (type& tree_node, container*) const = 0; @@ -754,12 +899,9 @@ 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) @@ -994,20 +1136,75 @@ namespace xsd XSD_AUTO_PTR map_; - private: - container* container_; - }; + // anyType and anySimpleType content. + // + protected: - inline _type:: - _type (const type& x, flags f, container* c) - : container_ (c) - { - if (x.dom_info_.get () != 0 && (f & flags::keep_dom)) + //@cond + + struct content_type { - dom_info_ = x.dom_info_->clone (*this, c); - } - } + virtual + ~content_type () {} + + content_type () {} + + virtual XSD_AUTO_PTR + 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 ()), dom (*doc) {} + explicit + dom_content_type (const xercesc::DOMElement& e) + : doc (xml::dom::create_document ()), dom (e, *doc) {} + + explicit + dom_content_type (xercesc::DOMElement* e) + : doc (xml::dom::create_document ()), dom (e, *doc) {} + + explicit + dom_content_type (const dom_content_optional& d) + : doc (xml::dom::create_document ()), dom (d, *doc) {} + + virtual XSD_AUTO_PTR + clone () const + { + return XSD_AUTO_PTR (new dom_content_type (dom)); + } + + virtual bool + compare (const content_type* c) const + { + if (const dom_content_type* dc = + dynamic_cast (c)) + return dom == dc->dom; + + return false; + } + + public: + XSD_DOM_AUTO_PTR doc; + dom_content_optional dom; + }; + + //@endcond + + mutable XSD_AUTO_PTR content_; + + private: + container* container_; + }; /** * @brief Class corresponding to the XML Schema anySimpleType built-in @@ -1015,7 +1212,7 @@ namespace xsd * * @nosubgrouping */ - template + template class simple_type: public B { public: @@ -1030,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 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& s); + public: /** * @brief Copy constructor. @@ -1074,7 +1277,9 @@ namespace xsd * instance. */ template - simple_type (istream& s, flags f = 0, container* c = 0); + simple_type (istream& s, + flags f = flags::extract_content, + container* c = 0); /** * @brief Create an instance from a DOM element. @@ -1085,7 +1290,7 @@ namespace xsd * instance. */ simple_type (const xercesc::DOMElement& e, - flags f = 0, + flags f = flags::extract_content, container* c = 0); /** @@ -1097,7 +1302,7 @@ namespace xsd * instance. */ simple_type (const xercesc::DOMAttr& a, - flags f = 0, + flags f = flags::extract_content, container* c = 0); /** @@ -1109,12 +1314,82 @@ namespace xsd * @param c A pointer to the object that will contain the new * instance. */ - template simple_type (const std::basic_string& 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& + text_content () const; + + /** + * @brief Return a read-write reference to the anySimpleType text + * content. + * + * @return A reference to the text string. + */ + std::basic_string& + text_content (); + + /** + * @brief Set the anySimpleType text content. + * + * @param e A new text string to set. + */ + void + text_content (const std::basic_string& 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& t): text (t) {} + + explicit + text_content_type (const C* t): text (t) {} + + virtual XSD_AUTO_PTR + clone () const + { + return XSD_AUTO_PTR (new text_content_type (text)); + } + + virtual bool + compare (const content_type* c) const + { + if (const text_content_type* tc = + dynamic_cast (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 text; + }; + + //@endcond }; @@ -1233,8 +1508,57 @@ namespace xsd { return XSD_AUTO_PTR (new T (s, e, f, c)); } + + // For now for istream we only go through traits for non- + // fundamental types. + // + template + static XSD_AUTO_PTR + create (istream& s, flags f, container* c) + { + return XSD_AUTO_PTR (new T (s, f, c)); + } }; + template + struct traits, C, ST> + { + typedef simple_type type; + + static XSD_AUTO_PTR + create (const xercesc::DOMElement& e, flags f, container* c) + { + return XSD_AUTO_PTR ( + new type (e, f | flags::extract_content, c)); + } + + static XSD_AUTO_PTR + create (const xercesc::DOMAttr& a, flags f, container* c) + { + return XSD_AUTO_PTR ( + new type (a, f | flags::extract_content, c)); + } + + static XSD_AUTO_PTR + create (const std::basic_string& s, + const xercesc::DOMElement* e, + flags f, + container* c) + { + return XSD_AUTO_PTR ( + new type (s, e, f | flags::extract_content, c)); + } + + template + static XSD_AUTO_PTR + create (istream& s, flags f, container* c) + { + return XSD_AUTO_PTR ( + new type (s, f | flags::extract_content, c)); + } + }; //@endcond diff --git a/libxsd/xsd/cxx/tree/elements.ixx b/libxsd/xsd/cxx/tree/elements.ixx index da8a83e..844ccf7 100644 --- a/libxsd/xsd/cxx/tree/elements.ixx +++ b/libxsd/xsd/cxx/tree/elements.ixx @@ -45,20 +45,221 @@ namespace xsd { } + inline _type:: + _type (const type& x, flags f, container* c) + : container_ (c) + { + if (x.content_.get () != 0) + content_ = x.content_->clone (); + + if (x.dom_info_.get () != 0 && (f & flags::keep_dom)) + { + dom_info_ = x.dom_info_->clone (*this, c); + } + } + + inline const _type::dom_content_optional& _type:: + dom_content () const + { + const content_type* c (content_.get ()); + + if (c == 0) + { + content_.reset (new dom_content_type); + c = content_.get (); + } + + // Accessing non-DOM content via the DOM API. + // + assert (dynamic_cast (c) != 0); + + return static_cast (c)->dom; + } + + inline _type::dom_content_optional& _type:: + dom_content () + { + content_type* c (content_.get ()); + + if (c == 0) + { + content_.reset (new dom_content_type); + c = content_.get (); + } + + // Accessing non-DOM content via the DOM API. + // + assert (dynamic_cast (c) != 0); + + return static_cast (c)->dom; + } + + inline void _type:: + dom_content (const xercesc::DOMElement& e) + { + content_type* c (content_.get ()); + + if (c == 0) + content_.reset (new dom_content_type (e)); + else + { + // Accessing non-DOM content via the DOM API. + // + assert (dynamic_cast (c) != 0); + static_cast (c)->dom.set (e); + } + } + + inline void _type:: + dom_content (xercesc::DOMElement* e) + { + content_type* c (content_.get ()); + + if (c == 0) + content_.reset (new dom_content_type (e)); + else + { + // Accessing non-DOM content via the DOM API. + // + assert (dynamic_cast (c) != 0); + static_cast (c)->dom.set (e); + } + } + + inline void _type:: + dom_content (const dom_content_optional& d) + { + content_type* c (content_.get ()); + + if (c == 0) + content_.reset (new dom_content_type (d)); + else + { + // Accessing non-DOM content via the DOM API. + // + assert (dynamic_cast (c) != 0); + static_cast (c)->dom = d; + } + } + + inline const xercesc::DOMDocument& _type:: + dom_content_document () const + { + const content_type* c (content_.get ()); + + if (c == 0) + { + content_.reset (new dom_content_type); + c = content_.get (); + } + + // Accessing non-DOM content via the DOM API. + // + assert (dynamic_cast (c) != 0); + + return *static_cast (c)->doc; + } + + inline xercesc::DOMDocument& _type:: + dom_content_document () + { + content_type* c (content_.get ()); + + if (c == 0) + { + content_.reset (new dom_content_type); + c = content_.get (); + } + + // Accessing non-DOM content via the DOM API. + // + assert (dynamic_cast (c) != 0); + + return *static_cast (c)->doc; + } + + inline bool _type:: + null_content () const + { + return content_.get () == 0; + } + // simple_type // - template - inline simple_type:: + template + inline simple_type:: simple_type () { } - template - template - inline simple_type:: - simple_type (const C*) + template + inline simple_type:: + simple_type (const C* s) + { + this->content_.reset (new text_content_type (s)); + } + + template + inline simple_type:: + simple_type (const std::basic_string& s) { + this->content_.reset (new text_content_type (s)); + } + + template + inline const std::basic_string& simple_type:: + text_content () const + { + const content_type* c (this->content_.get ()); + + if (c == 0) + { + this->content_.reset (new text_content_type); + c = this->content_.get (); + } + + // Accessing non-text content via the text API. + // + assert (dynamic_cast (c) != 0); + + return static_cast (c)->text; + } + + template + inline std::basic_string& simple_type:: + text_content () + { + content_type* c (this->content_.get ()); + + if (c == 0) + { + this->content_.reset (new text_content_type); + c = this->content_.get (); + } + + // Accessing non-text content via the text API. + // + assert (dynamic_cast (c) != 0); + + return static_cast (c)->text; + } + + template + inline void simple_type:: + text_content (const std::basic_string& t) + { + content_type* c (this->content_.get ()); + + if (c == 0) + this->content_.reset (new text_content_type (t)); + else + { + // Accessing non-text content via the text API. + // + assert (dynamic_cast (c) != 0); + static_cast (c)->text = t; + } } } } diff --git a/libxsd/xsd/cxx/tree/elements.txx b/libxsd/xsd/cxx/tree/elements.txx index 7389a86..4a8ca6e 100644 --- a/libxsd/xsd/cxx/tree/elements.txx +++ b/libxsd/xsd/cxx/tree/elements.txx @@ -27,8 +27,8 @@ namespace xsd // simple_type // - template - simple_type:: + template + simple_type:: simple_type (const simple_type& other, flags f, container* c) @@ -36,8 +36,8 @@ namespace xsd { } - template - simple_type* simple_type:: + template + simple_type* simple_type:: _clone (flags f, container* c) const { return new simple_type (*this, f, c); diff --git a/libxsd/xsd/cxx/tree/iterator-adapter.hxx b/libxsd/xsd/cxx/tree/iterator-adapter.hxx new file mode 100644 index 0000000..0a54604 --- /dev/null +++ b/libxsd/xsd/cxx/tree/iterator-adapter.hxx @@ -0,0 +1,270 @@ +// file : xsd/cxx/tree/iterator-adapter.hxx +// copyright : Copyright (c) 2005-2014 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#ifndef XSD_CXX_TREE_ITERATOR_ADAPTER_HXX +#define XSD_CXX_TREE_ITERATOR_ADAPTER_HXX + +#include // std::ptrdiff_t +#include // std::iterator_traits + +namespace xsd +{ + namespace cxx + { + namespace tree + { + // Sun CC's does not have iterator_traits. To overcome + // this, we will wrap std::iterator_traits into our own and also + // specialize it for pointer types. Since Sun CC uses pointer + // for vector::iterator, it will use the specialization and won't + // notice the std::iterator_traits. + // +#ifndef _RWSTD_NO_CLASS_PARTIAL_SPEC + template + struct iterator_traits + { + typedef + typename std::iterator_traits::iterator_category + iterator_category; + + typedef + typename std::iterator_traits::value_type + value_type; + + typedef + typename std::iterator_traits::difference_type + difference_type; + }; +#else + // The Pointer specialization does not work for reverse and + // set iterators. But these iterators are user-dfined types + // and have suitable typedefs that we can use. + // + template + struct iterator_traits + { + typedef typename I::iterator_category iterator_category; + typedef typename I::value_type value_type; + typedef typename I::difference_type difference_type; + }; + + template + struct iterator_traits + { + typedef std::random_access_iterator_tag iterator_category; + typedef T value_type; + typedef std::ptrdiff_t difference_type; + }; +#endif + + // Iterator adapter for complex types. It expects I to point to + // a smart pointer-like object that has operator*() that returns + // a refernce to a type static_cast'able to T and get() that + // returns a pointer to a type static_cast'able to T. + // + + template + struct iterator_adapter + { + typedef T value_type; + typedef value_type& reference; + typedef value_type* pointer; + + typedef + typename iterator_traits::iterator_category + iterator_category; + + typedef + typename iterator_traits::difference_type + difference_type; + + + public: + iterator_adapter () + : i_ () // i_ can be of a pointer type. + { + } + + // Allow iterator to const_iterator conversion. + // + template + iterator_adapter (const iterator_adapter& j) + : i_ (j.base ()) + { + } + + explicit + iterator_adapter (const I& i) + : i_ (i) + { + } + + public: + // Forward iterator requirements. + // + reference + operator* () const + { + return static_cast (**i_); + } + + pointer + operator-> () const + { + return static_cast (i_->get ()); + } + + iterator_adapter& + operator++ () + { + ++i_; + return *this; + } + + iterator_adapter + operator++ (int) + { + iterator_adapter r (*this); + ++i_; + return r; + } + + // Bidirectional iterator requirements. + // + iterator_adapter& + operator-- () + { + --i_; + return *this; + } + + iterator_adapter + operator-- (int) + { + iterator_adapter r (*this); + --i_; + return r; + } + + // Random access iterator requirements. + // + reference + operator[] (difference_type n) const + { + return static_cast (*(i_[n])); + } + + iterator_adapter& + operator+= (difference_type n) + { + i_ += n; + return *this; + } + + iterator_adapter + operator+ (difference_type n) const + { + return iterator_adapter (i_ + n); + } + + iterator_adapter& + operator-= (difference_type n) + { + i_ -= n; + return *this; + } + + iterator_adapter + operator- (difference_type n) const + { + return iterator_adapter (i_ - n); + } + + public: + const I& + base () const + { + return i_; + } + + private: + I i_; + }; + + // Note: We use different types for left- and right-hand-side + // arguments to allow comparison between iterator and const_iterator. + // + + // Forward iterator requirements. + // + template + inline bool + operator== (const iterator_adapter& i, + const iterator_adapter& j) + { + return i.base () == j.base (); + } + + template + inline bool + operator!= (const iterator_adapter& i, + const iterator_adapter& j) + { + return i.base () != j.base (); + } + + // Random access iterator requirements + // + template + inline bool + operator< (const iterator_adapter& i, + const iterator_adapter& j) + { + return i.base () < j.base (); + } + + template + inline bool + operator> (const iterator_adapter& i, + const iterator_adapter& j) + { + return i.base () > j.base (); + } + + template + inline bool + operator<= (const iterator_adapter& i, + const iterator_adapter& j) + { + return i.base () <= j.base (); + } + + template + inline bool + operator>= (const iterator_adapter& i, + const iterator_adapter& j) + { + return i.base () >= j.base (); + } + + template + inline typename iterator_adapter::difference_type + operator- (const iterator_adapter& i, + const iterator_adapter& j) + { + return i.base () - j.base (); + } + + template + inline iterator_adapter + operator+ (typename iterator_adapter::difference_type n, + const iterator_adapter& i) + { + return iterator_adapter (i.base () + n); + } + } + } +} + +#endif // XSD_CXX_TREE_ITERATOR_ADAPTER_HXX diff --git a/libxsd/xsd/cxx/tree/list.hxx b/libxsd/xsd/cxx/tree/list.hxx index 2b3b71e..d1fe907 100644 --- a/libxsd/xsd/cxx/tree/list.hxx +++ b/libxsd/xsd/cxx/tree/list.hxx @@ -10,7 +10,7 @@ #include #include -#include // tree::istream +#include #include // tree::istream #include // fundamental_p, sequence diff --git a/libxsd/xsd/cxx/tree/parsing.txx b/libxsd/xsd/cxx/tree/parsing.txx index 628b7fd..02aeda1 100644 --- a/libxsd/xsd/cxx/tree/parsing.txx +++ b/libxsd/xsd/cxx/tree/parsing.txx @@ -36,6 +36,9 @@ namespace xsd _type (const xercesc::DOMElement& e, flags f, container* c) : container_ (c) { + if (f & flags::extract_content) + content_.reset (new dom_content_type (e)); + if (f & flags::keep_dom) dom_info_ = dom_info_factory::create (e, *this, c == 0); } @@ -44,6 +47,8 @@ namespace xsd _type (const xercesc::DOMAttr& a, flags f, container* c) : container_ (c) { + // anyType cannot be an attribute type so no content extraction. + if (f & flags::keep_dom) dom_info_ = dom_info_factory::create (a, *this); } @@ -56,33 +61,41 @@ namespace xsd container* c) : container_ (c) // List elements don't have associated DOM nodes. { + // anyType cannot be a list element type so no content extraction. } // simple_type // - template - inline simple_type:: + template + inline simple_type:: simple_type (const xercesc::DOMElement& e, flags f, container* c) - : B (e, f, c) + : B (e, (f & ~flags::extract_content), c) { + if (f & flags::extract_content) + this->content_.reset ( + new text_content_type (tree::text_content (e))); } - template - inline simple_type:: + template + inline simple_type:: simple_type (const xercesc::DOMAttr& a, flags f, container* c) - : B (a, f, c) + : B (a, (f & ~flags::extract_content), c) { + if (f & flags::extract_content) + this->content_.reset (new text_content_type ( + xml::transcode (a.getValue ()))); } - template - template - inline simple_type:: + template + inline simple_type:: simple_type (const std::basic_string& s, const xercesc::DOMElement* e, flags f, container* c) - : B (s, e, f, c) + : B (s, e, (f & ~flags::extract_content), c) { + if (f & flags::extract_content) + this->content_.reset (new text_content_type (s)); } // fundamental_base @@ -161,7 +174,7 @@ namespace xsd } // Individual items of the list have no DOM association. Therefore - // I clear keep_dom from flags. + // we clear keep_dom from flags. // template @@ -203,7 +216,6 @@ namespace xsd return; using std::basic_string; - typedef typename sequence::ptr ptr; typedef typename basic_string::size_type size_type; const C* data (s.c_str ()); @@ -218,13 +230,12 @@ namespace xsd if (j != basic_string::npos) { - ptr r ( - new T (basic_string (data + i, j - i), - parent, - f, - this->container_)); - - this->v_.push_back (r); + this->push_back ( + traits::create ( + basic_string (data + i, j - i), + parent, + f, + this->container_)); i = bits::find_ns (data, size, j); } @@ -232,13 +243,12 @@ namespace xsd { // Last element. // - ptr r ( - new T (basic_string (data + i, size - i), - parent, - f, - this->container_)); - - this->v_.push_back (r); + this->push_back ( + traits::create ( + basic_string (data + i, size - i), + parent, + f, + this->container_)); break; } diff --git a/libxsd/xsd/cxx/tree/serialization.txx b/libxsd/xsd/cxx/tree/serialization.txx index e6fea1f..055f603 100644 --- a/libxsd/xsd/cxx/tree/serialization.txx +++ b/libxsd/xsd/cxx/tree/serialization.txx @@ -91,9 +91,29 @@ namespace xsd // Insertion operators for type. // inline void - operator<< (xercesc::DOMElement& e, const type&) + operator<< (xercesc::DOMElement& e, const type& x) { xml::dom::clear (e); + + if (!x.null_content () && x.dom_content ().present ()) + { + // Clone the contents of the element. + // + using namespace xercesc; + + DOMDocument& doc (*e.getOwnerDocument ()); + const DOMElement& se (x.dom_content ().get ()); + DOMNamedNodeMap& sa (*se.getAttributes ()); + + for (XMLSize_t i (0), n (sa.getLength ()); i != n; ++i) + e.setAttributeNode ( + static_cast (doc.importNode (sa.item (i), true))); + + for (DOMNode* sn (se.getFirstChild ()); + sn != 0; + sn = sn->getNextSibling ()) + e.appendChild (doc.importNode (sn, true)); + } } inline void @@ -109,23 +129,30 @@ namespace xsd // Insertion operators for simple_type. // - template + template inline void - operator<< (xercesc::DOMElement& e, const simple_type&) + operator<< (xercesc::DOMElement& e, const simple_type& x) { - xml::dom::clear (e); + if (x.null_content ()) + xml::dom::clear (e); + else + e << x.text_content (); } - template + template inline void - operator<< (xercesc::DOMAttr&, const simple_type&) + operator<< (xercesc::DOMAttr& a, const simple_type& x) { + if (!x.null_content ()) + a << x.text_content (); } template inline void - operator<< (list_stream&, const simple_type&) + operator<< (list_stream& ls, const simple_type& x) { + if (!x.null_content ()) + ls << x.text_content (); } // Insertion operators for list. diff --git a/libxsd/xsd/cxx/tree/std-ostream-map.txx b/libxsd/xsd/cxx/tree/std-ostream-map.txx index c79cdb6..ef65ef2 100644 --- a/libxsd/xsd/cxx/tree/std-ostream-map.txx +++ b/libxsd/xsd/cxx/tree/std-ostream-map.txx @@ -24,7 +24,7 @@ namespace xsd &inserter_impl, false); - typedef simple_type simple_type; + typedef simple_type simple_type; register_type ( typeid (simple_type), &inserter_impl, diff --git a/libxsd/xsd/cxx/tree/std-ostream-operators.hxx b/libxsd/xsd/cxx/tree/std-ostream-operators.hxx index 071d186..9a8f976 100644 --- a/libxsd/xsd/cxx/tree/std-ostream-operators.hxx +++ b/libxsd/xsd/cxx/tree/std-ostream-operators.hxx @@ -24,6 +24,7 @@ namespace xsd inline std::basic_ostream& operator<< (std::basic_ostream& os, const type&) { + // Not printing DOM content even if it's there. return os; } @@ -32,8 +33,11 @@ namespace xsd // template inline std::basic_ostream& - operator<< (std::basic_ostream& os, const simple_type&) + operator<< (std::basic_ostream& os, const simple_type& x) { + if (!x.null_content ()) + os << x.text_content (); + return os; } diff --git a/libxsd/xsd/cxx/tree/stream-extraction-map.txx b/libxsd/xsd/cxx/tree/stream-extraction-map.txx index 646ef83..61dd306 100644 --- a/libxsd/xsd/cxx/tree/stream-extraction-map.txx +++ b/libxsd/xsd/cxx/tree/stream-extraction-map.txx @@ -30,7 +30,7 @@ namespace xsd &extractor_impl, false); - typedef simple_type simple_type; + typedef simple_type simple_type; register_type ( qualified_name (bits::any_simple_type (), xsd), &extractor_impl, diff --git a/libxsd/xsd/cxx/tree/stream-extraction.hxx b/libxsd/xsd/cxx/tree/stream-extraction.hxx index b55afa0..ee39bcc 100644 --- a/libxsd/xsd/cxx/tree/stream-extraction.hxx +++ b/libxsd/xsd/cxx/tree/stream-extraction.hxx @@ -28,12 +28,18 @@ namespace xsd // simple_type // - template + template template - inline simple_type:: + inline simple_type:: simple_type (istream& s, flags f, container* c) - : type (s, f, c) + : type (s, f & ~flags::extract_content, c) { + if (f & flags::extract_content) + { + std::basic_string t; + s >> t; + this->content_.reset (new text_content_type (t)); + } } // fundamental_base @@ -65,9 +71,7 @@ namespace xsd this->reserve (size); while (size--) - { - this->push_back (XSD_AUTO_PTR (new T (s, f, c))); - } + this->push_back (traits::create (s, f, c)); } } diff --git a/libxsd/xsd/cxx/tree/stream-insertion-map.txx b/libxsd/xsd/cxx/tree/stream-insertion-map.txx index 1550826..78fbacb 100644 --- a/libxsd/xsd/cxx/tree/stream-insertion-map.txx +++ b/libxsd/xsd/cxx/tree/stream-insertion-map.txx @@ -31,7 +31,7 @@ namespace xsd &inserter_impl, false); - typedef simple_type simple_type; + typedef simple_type simple_type; register_type ( typeid (simple_type), qualified_name (bits::any_simple_type (), xsd), diff --git a/libxsd/xsd/cxx/tree/stream-insertion.hxx b/libxsd/xsd/cxx/tree/stream-insertion.hxx index 7f1f5df..b04846f 100644 --- a/libxsd/xsd/cxx/tree/stream-insertion.hxx +++ b/libxsd/xsd/cxx/tree/stream-insertion.hxx @@ -23,15 +23,19 @@ namespace xsd inline ostream& operator<< (ostream& s, const type&) { + // Not saving DOM content even if it's there. return s; } // simple_type // - template + template inline ostream& - operator<< (ostream& s, const simple_type&) + operator<< (ostream& s, const simple_type& x) { + if (!x.null_content ()) + s << x.text_content (); + return s; } diff --git a/libxsd/xsd/cxx/tree/type-factory-map.txx b/libxsd/xsd/cxx/tree/type-factory-map.txx index 8ccbc63..e1fe0cc 100644 --- a/libxsd/xsd/cxx/tree/type-factory-map.txx +++ b/libxsd/xsd/cxx/tree/type-factory-map.txx @@ -37,7 +37,7 @@ namespace xsd &factory_impl, false); - typedef simple_type simple_type; + typedef simple_type simple_type; register_type ( qualified_name (bits::any_simple_type (), xsd), &factory_impl, diff --git a/libxsd/xsd/cxx/tree/type-serializer-map.txx b/libxsd/xsd/cxx/tree/type-serializer-map.txx index 353ccae..dd47a00 100644 --- a/libxsd/xsd/cxx/tree/type-serializer-map.txx +++ b/libxsd/xsd/cxx/tree/type-serializer-map.txx @@ -38,7 +38,7 @@ namespace xsd &serializer_impl, false); - typedef simple_type simple_type; + typedef simple_type simple_type; register_type ( typeid (simple_type), qualified_name (bits::any_simple_type (), xsd), diff --git a/libxsd/xsd/cxx/tree/types.hxx b/libxsd/xsd/cxx/tree/types.hxx index 61a1e1a..288a291 100644 --- a/libxsd/xsd/cxx/tree/types.hxx +++ b/libxsd/xsd/cxx/tree/types.hxx @@ -271,6 +271,29 @@ namespace xsd } }; + /** + * @brief %string comparison operator. + * + * @return True if the strings are equal, false otherwise. + */ + template + inline bool + operator== (const string& a, const string& b) + { + return static_cast&> (a) == b; + } + + /** + * @brief %string comparison operator. + * + * @return True if the strings are not equal, false otherwise. + */ + template + inline bool + operator!= (const string& a, const string& b) + { + return !(a == b); + } /** * @brief Class corresponding to the XML Schema normalizedString @@ -1119,6 +1142,31 @@ namespace xsd //@} }; + /** + * @brief %nmtokens comparison operator. + * + * @return True if the lists of nmtokens are equal, false otherwise. + */ + template + inline bool + operator== (const nmtokens& a, + const nmtokens& b) + { + return static_cast&> (a) == b; + } + + /** + * @brief %nmtokens comparison operator. + * + * @return True if the lists of nmtokens are not equal, false otherwise. + */ + template + inline bool + operator!= (const nmtokens& a, + const nmtokens& b) + { + return !(a == b); + } /** * @brief Class corresponding to the XML Schema Name built-in @@ -2575,6 +2623,29 @@ namespace xsd //@} }; + /** + * @brief %idrefs comparison operator. + * + * @return True if the lists of idrefs are equal, false otherwise. + */ + template + inline bool + operator== (const idrefs& a, const idrefs& b) + { + return static_cast&> (a) == b; + } + + /** + * @brief %idrefs comparison operator. + * + * @return True if the lists of idrefs are not equal, false otherwise. + */ + template + inline bool + operator!= (const idrefs& a, const idrefs& b) + { + return !(a == b); + } /** * @brief Class corresponding to the XML Schema anyURI built-in @@ -2811,6 +2882,29 @@ namespace xsd friend class qname; }; + /** + * @brief %uri comparison operator. + * + * @return True if the uris are equal, false otherwise. + */ + template + inline bool + operator== (const uri& a, const uri& b) + { + return static_cast&> (a) == b; + } + + /** + * @brief %uri comparison operator. + * + * @return True if the uris are not equal, false otherwise. + */ + template + inline bool + operator!= (const uri& a, const uri& b) + { + return !(a == b); + } /** * @brief Class corresponding to the XML Schema QName built-in @@ -3211,6 +3305,29 @@ namespace xsd decode (const XMLCh*); }; + /** + * @brief %base64_binary comparison operator. + * + * @return True if the binaries are equal, false otherwise. + */ + template + inline bool + operator== (const base64_binary& a, const base64_binary& b) + { + return static_cast&> (a) == b; + } + + /** + * @brief %base64_binary comparison operator. + * + * @return True if the binaries are not equal, false otherwise. + */ + template + inline bool + operator!= (const base64_binary& a, const base64_binary& b) + { + return !(a == b); + } /** * @brief Class corresponding to the XML Schema hexBinary @@ -3404,6 +3521,29 @@ namespace xsd decode (const XMLCh*); }; + /** + * @brief %hex_binary comparison operator. + * + * @return True if the binaries are equal, false otherwise. + */ + template + inline bool + operator== (const hex_binary& a, const hex_binary& b) + { + return static_cast&> (a) == b; + } + + /** + * @brief %hex_binary comparison operator. + * + * @return True if the binaries are not equal, false otherwise. + */ + template + inline bool + operator!= (const hex_binary& a, const hex_binary& b) + { + return !(a == b); + } /** * @brief Class corresponding to the XML Schema ENTITY built-in @@ -3768,6 +3908,32 @@ namespace xsd container* c = 0); //@} }; + + /** + * @brief %entities comparison operator. + * + * @return True if the lists of entities are equal, false otherwise. + */ + template + inline bool + operator== (const entities& a, + const entities& b) + { + return static_cast&> (a) == b; + } + + /** + * @brief %entities comparison operator. + * + * @return True if the lists of entities are not equal, false otherwise. + */ + template + inline bool + operator!= (const entities& a, + const entities& b) + { + return !(a == b); + } } } } diff --git a/libxsd/xsd/cxx/xml/string.hxx b/libxsd/xsd/cxx/xml/string.hxx index dbc78b4..9f4767b 100644 --- a/libxsd/xsd/cxx/xml/string.hxx +++ b/libxsd/xsd/cxx/xml/string.hxx @@ -56,21 +56,16 @@ namespace xsd public : template string (const std::basic_string& s) - : s_ (transcode_to_xmlch (s)) - { - } + : s_ (transcode_to_xmlch (s)) {} template - string (const C* s) - : s_ (transcode_to_xmlch (s)) - { - } + string (const C* s): s_ (transcode_to_xmlch (s)) {} const XMLCh* - c_str () const - { - return s_.get (); - } + c_str () const {return s_.get ();} + + XMLCh* + release () {return s_.release ();} private: string (const string&); diff --git a/tests/cxx/tree/any-type/driver.cxx b/tests/cxx/tree/any-type/driver.cxx new file mode 100644 index 0000000..1ac5274 --- /dev/null +++ b/tests/cxx/tree/any-type/driver.cxx @@ -0,0 +1,145 @@ +// file : tests/cxx/tree/any-type/driver.cxx +// copyright : Copyright (c) 2006-2014 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +// Test anyType and anySimpleType content extraction. +// + +#include // std::auto_ptr/unique_ptr +#include // std::move +#include +#include + +#include +#include + +#include "test.hxx" // Get XSD_CXX11 defined. + +#include + +using namespace std; +using namespace test; +using namespace xercesc; + +namespace xml = xsd::cxx::xml; + +int +main (int argc, char* argv[]) +{ + if (argc != 2) + { + cerr << "usage: " << argv[0] << " test.xml" << endl; + return 1; + } + + XMLPlatformUtils::Initialize (); + + try + { + // Test parsing + // + XSD_AUTO_PTR r (root (argv[1])); + + // Test API. + // + { + assert (type::a_default_value ().text_content () == "default value"); + } + + { + xml_schema::simple_type x ("fox"); + assert (x.text_content () == "fox"); + x.text_content ("foo"); + assert (x.text_content () == "foo"); + x.text_content ().clear (); + assert (x.text_content () == ""); + x.text_content () = "baz"; + r->s ().push_back (x); + } + + { + xml_schema::type x; + + DOMDocument& doc (x.dom_content_document ()); + + // Copy. + // + DOMElement* e (doc.createElement (xml::string ("dummy").c_str ())); + e->setAttribute (xml::string ("x").c_str (), + xml::string ("foo").c_str ()); + e->setTextContent (xml::string ("data").c_str ()); + x.dom_content ().set (*e); + e->release (); + + r->t ().push_back (x); + } + + { + XSD_AUTO_PTR x (new xml_schema::type); + + DOMDocument& doc (x->dom_content_document ()); + + // Assume ownership. + // + DOMElement* e (doc.createElement (xml::string ("dummy").c_str ())); + e->setAttribute (xml::string ("x").c_str (), + xml::string ("foo").c_str ()); + e->setTextContent (xml::string ("data").c_str ()); + x->dom_content ().set (e); + +#ifdef XSD_CXX11 + r->t ().push_back (std::move (x)); +#else + r->t ().push_back (x); +#endif + } + + // Test printing. + // + cout << *r << endl + << endl; + + // Test serialization. + // + xml_schema::namespace_infomap map; + + map["t"].name = "test"; + map["t"].schema = "test.xsd"; + map["o"].name = "other"; + + stringstream iostr; + root (iostr, *r, map); + + cout << iostr.str () << endl + << endl; + + { + XSD_AUTO_PTR r1 (root (iostr, argv[1])); + + // Xerces-C++ mis-indentation of mixed content messes this up. + // assert (*r == *r); + + stringstream iostr; + root (iostr, *r1, map); + + cout << iostr.str () << endl + << endl; + } + + // Test comparison. + // + assert (*r == *r); + + // Test copy c-tor. + // + type copy (*r); + assert (copy == *r); + } + catch (xml_schema::exception const& e) + { + cerr << e << endl; + return 1; + } + + XMLPlatformUtils::Terminate (); +} diff --git a/tests/cxx/tree/any-type/makefile b/tests/cxx/tree/any-type/makefile new file mode 100644 index 0000000..1d0590f --- /dev/null +++ b/tests/cxx/tree/any-type/makefile @@ -0,0 +1,87 @@ +# file : tests/cxx/tree/any-type/makefile +# copyright : Copyright (c) 2006-2014 Code Synthesis Tools CC +# license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +include $(dir $(lastword $(MAKEFILE_LIST)))../../../../build/bootstrap.make + +xsd := test.xsd +cxx := driver.cxx + +obj := $(addprefix $(out_base)/,$(cxx:.cxx=.o) $(xsd:.xsd=.o)) +dep := $(obj:.o=.o.d) + +driver := $(out_base)/driver +test := $(out_base)/.test +clean := $(out_base)/.clean + + +# Import. +# +$(call import,\ + $(scf_root)/import/libxerces-c/stub.make,\ + l: xerces_c.l,cpp-options: xerces_c.l.cpp-options) + + +# Build. +# +$(driver): $(obj) $(xerces_c.l) + +$(obj) $(dep): cpp_options := -I$(out_base) -I$(src_base) -I$(src_root)/libxsd +$(obj) $(dep): $(xerces_c.l.cpp-options) + +genf := $(xsd:.xsd=.hxx) $(xsd:.xsd=.ixx) $(xsd:.xsd=.cxx) +gen := $(addprefix $(out_base)/,$(genf)) + +$(gen): xsd := $(out_root)/xsd/xsd +$(gen): xsd_options += --generate-any-type --generate-serialization \ +--generate-ostream --generate-comparison +$(gen): $(out_root)/xsd/xsd + +$(call include-dep,$(dep),$(obj),$(gen)) + +# Convenience alias for default target. +# +$(out_base)/: $(driver) + + +# Test. +# +$(test): driver := $(driver) +$(test): $(driver) $(src_base)/test.xml $(src_base)/output + $(call message,test $$1,$$1 $(src_base)/test.xml | diff -u $(src_base)/output -,$(driver)) + +# Clean. +# +$(clean): $(driver).o.clean \ + $(addsuffix .cxx.clean,$(obj)) \ + $(addsuffix .cxx.clean,$(dep)) \ + $(addprefix $(out_base)/,$(xsd:.xsd=.cxx.xsd.clean)) + +# Generated .gitignore. +# +ifeq ($(out_base),$(src_base)) +$(gen): | $(out_base)/.gitignore +$(driver): | $(out_base)/.gitignore + +$(out_base)/.gitignore: files := driver $(genf) +$(clean): $(out_base)/.gitignore.clean + +$(call include,$(bld_root)/git/gitignore.make) +endif + +# How to. +# +$(call include,$(bld_root)/cxx/o-e.make) +$(call include,$(bld_root)/cxx/cxx-o.make) +$(call include,$(bld_root)/cxx/cxx-d.make) + +$(call include,$(bld_root)/cxx/standard.make) # cxx_standard +ifdef cxx_standard +$(gen): xsd_options += --std $(cxx_standard) +$(call include,$(scf_root)/xsd/tree/xsd-cxx.make) +endif + + +# Dependencies. +# +$(call import,$(src_root)/xsd/makefile) diff --git a/tests/cxx/tree/any-type/output b/tests/cxx/tree/any-type/output new file mode 100644 index 0000000..580e7db --- /dev/null +++ b/tests/cxx/tree/any-type/output @@ -0,0 +1,73 @@ + +t: +t: +t: +t: +t: +t: +t: +t: +s: +s: simple +s: baz +l: one two three +a: any simple content + + + + + + any + any + + + nested 1 + nested 2 + + more + + mi + nested 1x + nested 2ed + content + + data + data + + simple + baz + one two three + + + + + + + + any + any + + + nested 1 + nested 2 + + more + + mi + + nested 1x + + nested 2ed + + content + + + data + data + + simple + baz + one two three + + + diff --git a/tests/cxx/tree/any-type/test.xml b/tests/cxx/tree/any-type/test.xml new file mode 100644 index 0000000..7c9035a --- /dev/null +++ b/tests/cxx/tree/any-type/test.xml @@ -0,0 +1,26 @@ + + + + + any + any + + + nested 1 + nested 2 + + more + + minested 1xnested 2edcontent + + + simple + + one two three + + diff --git a/tests/cxx/tree/any-type/test.xsd b/tests/cxx/tree/any-type/test.xsd new file mode 100644 index 0000000..37dcc8d --- /dev/null +++ b/tests/cxx/tree/any-type/test.xsd @@ -0,0 +1,19 @@ + + + + + + + + + + + + + + + + + + + diff --git a/tests/cxx/tree/binary/cdr/driver.cxx b/tests/cxx/tree/binary/cdr/driver.cxx index 65c88fa..a2d7195 100644 --- a/tests/cxx/tree/binary/cdr/driver.cxx +++ b/tests/cxx/tree/binary/cdr/driver.cxx @@ -127,6 +127,14 @@ main (int argc, char* argv[]) assert (r->time () == c->time ()); assert (r->date_time () == c->date_time ()); assert (r->duration () == c->duration ()); + + // anySimpleType + // + assert (!r->any_simple_type_attr ().text_content ().empty ()); + assert (r->any_simple_type_attr () == c->any_simple_type_attr ()); + + assert (!r->any_simple_type ().text_content ().empty ()); + assert (r->any_simple_type () == c->any_simple_type ()); } catch (xml_schema::exception const& e) { diff --git a/tests/cxx/tree/binary/cdr/makefile b/tests/cxx/tree/binary/cdr/makefile index 9613841..eb80d35 100644 --- a/tests/cxx/tree/binary/cdr/makefile +++ b/tests/cxx/tree/binary/cdr/makefile @@ -37,7 +37,7 @@ gen := $(addprefix $(out_base)/,$(genf)) $(gen): xsd := $(out_root)/xsd/xsd $(gen): xsd_options += --generate-insertion ACE_OutputCDR \ ---generate-extraction ACE_InputCDR +--generate-extraction ACE_InputCDR --generate-comparison $(gen): $(out_root)/xsd/xsd $(call include-dep,$(dep),$(obj),$(gen)) diff --git a/tests/cxx/tree/binary/cdr/test.xml b/tests/cxx/tree/binary/cdr/test.xml index 928b4cf..5cedd98 100644 --- a/tests/cxx/tree/binary/cdr/test.xml +++ b/tests/cxx/tree/binary/cdr/test.xml @@ -1,6 +1,7 @@ + xsi:schemaLocation="test test.xsd" + any_simple_type_attr="any simple content"> 1 2 3 @@ -87,5 +88,6 @@ 2001-11+02:00 + any simple content in element diff --git a/tests/cxx/tree/binary/cdr/test.xsd b/tests/cxx/tree/binary/cdr/test.xsd index e593f64..0629e94 100644 --- a/tests/cxx/tree/binary/cdr/test.xsd +++ b/tests/cxx/tree/binary/cdr/test.xsd @@ -112,7 +112,10 @@ + + + diff --git a/tests/cxx/tree/binary/polymorphic/makefile b/tests/cxx/tree/binary/polymorphic/makefile index f9ddf67..05c5186 100644 --- a/tests/cxx/tree/binary/polymorphic/makefile +++ b/tests/cxx/tree/binary/polymorphic/makefile @@ -37,7 +37,8 @@ gen := $(addprefix $(out_base)/,$(genf)) $(gen): xsd := $(out_root)/xsd/xsd $(gen): xsd_options += --generate-polymorphic --root-element-last \ ---generate-insertion ACE_OutputCDR --generate-extraction ACE_InputCDR +--generate-insertion ACE_OutputCDR --generate-extraction ACE_InputCDR \ + --generate-comparison $(gen): $(out_root)/xsd/xsd $(call include-dep,$(dep),$(obj),$(gen)) diff --git a/tests/cxx/tree/binary/xdr/driver.cxx b/tests/cxx/tree/binary/xdr/driver.cxx index ddc196d..623a953 100644 --- a/tests/cxx/tree/binary/xdr/driver.cxx +++ b/tests/cxx/tree/binary/xdr/driver.cxx @@ -171,6 +171,14 @@ main (int argc, char* argv[]) assert (r->year () == c->year ()); assert (r->year_month () == c->year_month ()); assert (r->time () == c->time ()); + + // anySimpleType + // + assert (!r->any_simple_type_attr ().text_content ().empty ()); + assert (r->any_simple_type_attr () == c->any_simple_type_attr ()); + + assert (!r->any_simple_type ().text_content ().empty ()); + assert (r->any_simple_type () == c->any_simple_type ()); } catch (xml_schema::exception const& e) { diff --git a/tests/cxx/tree/binary/xdr/makefile b/tests/cxx/tree/binary/xdr/makefile index 184c5d2..2994134 100644 --- a/tests/cxx/tree/binary/xdr/makefile +++ b/tests/cxx/tree/binary/xdr/makefile @@ -32,7 +32,8 @@ genf := $(xsd:.xsd=.hxx) $(xsd:.xsd=.ixx) $(xsd:.xsd=.cxx) gen := $(addprefix $(out_base)/,$(genf)) $(gen): xsd := $(out_root)/xsd/xsd -$(gen): xsd_options += --generate-insertion XDR --generate-extraction XDR +$(gen): xsd_options += --generate-insertion XDR --generate-extraction XDR \ +--generate-comparison $(gen): $(out_root)/xsd/xsd $(call include-dep,$(dep),$(obj),$(gen)) diff --git a/tests/cxx/tree/binary/xdr/test.xml b/tests/cxx/tree/binary/xdr/test.xml index 928b4cf..5cedd98 100644 --- a/tests/cxx/tree/binary/xdr/test.xml +++ b/tests/cxx/tree/binary/xdr/test.xml @@ -1,6 +1,7 @@ + xsi:schemaLocation="test test.xsd" + any_simple_type_attr="any simple content"> 1 2 3 @@ -87,5 +88,6 @@ 2001-11+02:00 + any simple content in element diff --git a/tests/cxx/tree/binary/xdr/test.xsd b/tests/cxx/tree/binary/xdr/test.xsd index e593f64..0629e94 100644 --- a/tests/cxx/tree/binary/xdr/test.xsd +++ b/tests/cxx/tree/binary/xdr/test.xsd @@ -112,7 +112,10 @@ + + + diff --git a/tests/cxx/tree/compilation/driver.cxx b/tests/cxx/tree/compilation/driver.cxx index c396ec5..c2e6298 100644 --- a/tests/cxx/tree/compilation/driver.cxx +++ b/tests/cxx/tree/compilation/driver.cxx @@ -13,7 +13,7 @@ using namespace std; using namespace test; -template class xsd::cxx::tree::simple_type; +template class xsd::cxx::tree::simple_type; // String types. // diff --git a/tests/cxx/tree/makefile b/tests/cxx/tree/makefile index cd081e8..7fd9f63 100644 --- a/tests/cxx/tree/makefile +++ b/tests/cxx/tree/makefile @@ -5,6 +5,7 @@ include $(dir $(lastword $(MAKEFILE_LIST)))../../../build/bootstrap.make tests := \ +any-type \ built-in \ chameleon \ comparison \ diff --git a/xsd/cxx/tree/fundamental-header.hxx b/xsd/cxx/tree/fundamental-header.hxx index 1145c0c..925d65e 100644 --- a/xsd/cxx/tree/fundamental-header.hxx +++ b/xsd/cxx/tree/fundamental-header.hxx @@ -241,7 +241,7 @@ namespace CXX traverse (SemanticGraph::AnySimpleType& t) { simple_type_ = built_in_type ( - t, L"::xsd::cxx::tree::simple_type< ", type_); + t, L"::xsd::cxx::tree::simple_type< " + char_type + L", ", type_); if (doxygen) os << "/**" << endl diff --git a/xsd/cxx/tree/options.cli b/xsd/cxx/tree/options.cli index 026e4a1..f1b343a 100644 --- a/xsd/cxx/tree/options.cli +++ b/xsd/cxx/tree/options.cli @@ -170,6 +170,13 @@ namespace CXX this option." }; + bool --generate-any-type + { + "Extract and store content of the XML Schema \cb{anyType} type as a + DOM fragment. Note that you need to initialize the Xerces-C++ runtime + if you are using this option." + }; + NarrowStrings --generate-insertion { "", diff --git a/xsd/cxx/tree/stream-extraction-source.cxx b/xsd/cxx/tree/stream-extraction-source.cxx index a1ca4bc..ceb56c1 100644 --- a/xsd/cxx/tree/stream-extraction-source.cxx +++ b/xsd/cxx/tree/stream-extraction-source.cxx @@ -321,6 +321,7 @@ namespace CXX SemanticGraph::Type& t (e.type ()); String type (etype (e)); + String tr (etraits (e)); // traits type name bool fund (false); { @@ -389,8 +390,8 @@ namespace CXX } else { - os << auto_ptr << "< " << type << " > r (new " << type << - " (s, f, this));"; + os << auto_ptr << "< " << type << " > r (" << endl + << tr << "::create (s, f, this));"; } os << "c.push_back (" << r << ");" @@ -438,8 +439,8 @@ namespace CXX } else { - os << auto_ptr << "< " << type << " > r (new " << type << - " (s, f, this));"; + os << auto_ptr << "< " << type << " > r (" << endl + << tr << "::create (s, f, this));"; } os << "this->" << member << ".set (" << r << ");" @@ -482,8 +483,8 @@ namespace CXX } else { - os << auto_ptr << "< " << type << " > r (new " << type << - " (s, f, this));"; + os << auto_ptr << "< " << type << " > r (" << endl + << tr << "::create (s, f, this));"; } os << "this->" << member << ".set (" << r << ");" @@ -507,6 +508,7 @@ namespace CXX { String const& member (emember (a)); String type (etype (a)); + String tr (etraits (a)); // traits type name bool fund (false); { @@ -530,8 +532,8 @@ namespace CXX } else { - os << "this->" << member << ".set (" << auto_ptr << "< " << - type << " > (new " << type << " (s, f, this)));"; + os << "this->" << member << ".set (" << tr << + "::create (s, f, this));"; } os << "}" // if (p) @@ -549,8 +551,8 @@ namespace CXX } else { - os << "this->" << member << ".set (" << auto_ptr << "< " << - type << " > (new " << type << " (s, f, this)));"; + os << "this->" << member << ".set (" << tr << + "::create (s, f, this));"; } os << "}"; diff --git a/xsd/cxx/tree/tree-header.cxx b/xsd/cxx/tree/tree-header.cxx index e6c2411..f0c3560 100644 --- a/xsd/cxx/tree/tree-header.cxx +++ b/xsd/cxx/tree/tree-header.cxx @@ -291,6 +291,22 @@ namespace CXX << "~" << name << " ();"; os << "};"; + + // Comparison operators. + // + if (options.generate_comparison ()) + { + os << inst_exp + << "bool" << endl + << "operator== (const " << name << "&, const " << name << "&);" + << endl; + + os << inst_exp + << "bool" << endl + << "operator!= (const " << name << "&, const " << name << "&);" + << endl + << endl; + } } private: diff --git a/xsd/cxx/tree/tree-inline.cxx b/xsd/cxx/tree/tree-inline.cxx index e6ed756..500ee73 100644 --- a/xsd/cxx/tree/tree-inline.cxx +++ b/xsd/cxx/tree/tree-inline.cxx @@ -82,6 +82,28 @@ namespace CXX << " " << base_type << " (o, f, this)" << "{" << "}"; + + // Comparison operators. + // + if (options.generate_comparison ()) + { + os << inl + << "bool" << endl + << "operator== (const " << name << "& x, " << + "const " << name << "& y)" + << "{" + << "const " << base_type << "& bx (x);" + << "return bx == y;" + << "}"; + + os << inl + << "bool" << endl + << "operator!= (const " << name << "& x, " << + "const " << name << "& y)" + << "{" + << "return !(x == y);" + << "}"; + } } private: diff --git a/xsd/cxx/tree/tree-source.cxx b/xsd/cxx/tree/tree-source.cxx index 110cb25..9524463 100644 --- a/xsd/cxx/tree/tree-source.cxx +++ b/xsd/cxx/tree/tree-source.cxx @@ -756,7 +756,13 @@ namespace CXX if (!fund) { os << auto_ptr << "< " << type << " > r (" << endl - << tr << "::create (i, f, this));" + << tr << "::create (i, f"; + + if (t.is_a () && + options.generate_any_type ()) + os << " | " << flags_type << "::extract_content"; + + os << ", this));" << endl; } } -- cgit v1.1