From f0510d2f90467de8e8f260b47d79a9baaf9bef17 Mon Sep 17 00:00:00 2001 From: Boris Kolpackov Date: Thu, 17 Sep 2009 07:15:29 +0200 Subject: Start tracking XSD with git --- libxsd/xsd/cxx/parser/non-validating/parser.txx | 464 ++++++++++++++++++++++++ 1 file changed, 464 insertions(+) create mode 100644 libxsd/xsd/cxx/parser/non-validating/parser.txx (limited to 'libxsd/xsd/cxx/parser/non-validating/parser.txx') diff --git a/libxsd/xsd/cxx/parser/non-validating/parser.txx b/libxsd/xsd/cxx/parser/non-validating/parser.txx new file mode 100644 index 0000000..d379d7a --- /dev/null +++ b/libxsd/xsd/cxx/parser/non-validating/parser.txx @@ -0,0 +1,464 @@ +// file : xsd/cxx/parser/non-validating/parser.txx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#include + +#include + +namespace xsd +{ + namespace cxx + { + namespace parser + { + namespace non_validating + { + + // empty_content + // + + template + void empty_content:: + _start_any_element (const ro_string&, + const ro_string&, + const ro_string*) + { + } + + template + void empty_content:: + _end_any_element (const ro_string&, + const ro_string&) + { + } + + template + void empty_content:: + _any_attribute (const ro_string&, + const ro_string&, + const ro_string&) + { + } + + template + void empty_content:: + _any_characters (const ro_string&) + { + } + + // + // + template + bool empty_content:: + _start_element_impl (const ro_string&, + const ro_string&, + const ro_string*) + { + return false; + } + + template + bool empty_content:: + _end_element_impl (const ro_string&, + const ro_string&) + { + return false; + } + + template + bool empty_content:: + _attribute_impl (const ro_string&, + const ro_string&, + const ro_string&) + { + return false; + } + + template + bool empty_content:: + _characters_impl (const ro_string&) + { + return false; + } + + template + void empty_content:: + _start_element (const ro_string& ns, + const ro_string& name, + const ro_string* type) + { + if (!_start_element_impl (ns, name, type)) + _start_any_element (ns, name, type); + } + + template + void empty_content:: + _end_element (const ro_string& ns, + const ro_string& name) + { + if (!_end_element_impl (ns, name)) + _end_any_element (ns, name); + } + + template + void empty_content:: + _attribute (const ro_string& ns, + const ro_string& name, + const ro_string& value) + { + // Weed out special attributes: xsi:type, xsi:nil, + // xsi:schemaLocation and noNamespaceSchemaLocation. + // See section 3.2.7 in Structures for details. + // + if (ns == xml::bits::xsi_namespace () && + (name == xml::bits::type () || + name == xml::bits::nil () || + name == xml::bits::schema_location () || + name == xml::bits::no_namespace_schema_location ())) + return; + + // Also some parsers (notably Xerces-C++) supplies us with + // namespace-prefix mapping attributes. + // + if (ns == xml::bits::xmlns_namespace ()) + return; + + if (!_attribute_impl (ns, name, value)) + _any_attribute (ns, name, value); + } + + template + void empty_content:: + _characters (const ro_string& s) + { + if (!_characters_impl (s)) + _any_characters (s); + } + + + // simple_content + // + + template + void simple_content:: + _attribute (const ro_string& ns, + const ro_string& name, + const ro_string& value) + { + // Weed out special attributes: xsi:type, xsi:nil, + // xsi:schemaLocation and xsi:noNamespaceSchemaLocation. + // See section 3.2.7 in Structures for details. + // + if (ns == xml::bits::xsi_namespace () && + (name == xml::bits::type () || + name == xml::bits::nil () || + name == xml::bits::schema_location () || + name == xml::bits::no_namespace_schema_location ())) + return; + + // Also some parsers (notably Xerces-C++) supplies us with + // namespace-prefix mapping attributes. + // + if (ns == xml::bits::xmlns_namespace ()) + return; + + if (!_attribute_impl (ns, name, value)) + _any_attribute (ns, name, value); + } + + template + void simple_content:: + _characters (const ro_string& str) + { + _characters_impl (str); + } + + + // complex_content + // + + template + void complex_content:: + _start_element (const ro_string& ns, + const ro_string& name, + const ro_string* type) + { + state& s (context_.top ()); + + if (s.depth_++ > 0) + { + if (s.any_) + _start_any_element (ns, name, type); + else if (s.parser_) + s.parser_->_start_element (ns, name, type); + } + else + { + if (!_start_element_impl (ns, name, type)) + { + _start_any_element (ns, name, type); + s.any_ = true; + } + else if (s.parser_ != 0) + s.parser_->_pre_impl (); + } + } + + template + void complex_content:: + _end_element (const ro_string& ns, + const ro_string& name) + { + // To understand what's going on here it is helpful to think of + // a "total depth" as being the sum of individual depths over + // all elements. + // + + if (context_.top ().depth_ == 0) + { + state& s (context_.under_top ()); // One before last. + + if (--s.depth_ > 0) + { + // Indirect recursion. + // + if (s.parser_) + s.parser_->_end_element (ns, name); + } + else + { + // Direct recursion. + // + assert (this == s.parser_); + + this->_post_impl (); + + if (!_end_element_impl (ns, name)) + assert (false); + } + } + else + { + state& s (context_.top ()); + + if (--s.depth_ > 0) + { + if (s.any_) + _end_any_element (ns, name); + else if (s.parser_) + s.parser_->_end_element (ns, name); + } + else + { + if (s.parser_ != 0 && !s.any_) + s.parser_->_post_impl (); + + if (!_end_element_impl (ns, name)) + { + s.any_ = false; + _end_any_element (ns, name); + } + } + } + } + + template + void complex_content:: + _attribute (const ro_string& ns, + const ro_string& name, + const ro_string& value) + { + // Weed out special attributes: xsi:type, xsi:nil, + // xsi:schemaLocation and xsi:noNamespaceSchemaLocation. + // See section 3.2.7 in Structures for details. + // + if (ns == xml::bits::xsi_namespace () && + (name == xml::bits::type () || + name == xml::bits::nil () || + name == xml::bits::schema_location () || + name == xml::bits::no_namespace_schema_location ())) + return; + + // Also some parsers (notably Xerces-C++) supplies us with + // namespace-prefix mapping attributes. + // + if (ns == xml::bits::xmlns_namespace ()) + return; + + state& s (context_.top ()); + + if (s.depth_ > 0) + { + if (s.any_) + _any_attribute (ns, name, value); + else if (s.parser_) + s.parser_->_attribute (ns, name, value); + } + else + { + if (!_attribute_impl (ns, name, value)) + _any_attribute (ns, name, value); + } + } + + template + void complex_content:: + _characters (const ro_string& str) + { + state& s (context_.top ()); + + if (s.depth_ > 0) + { + if (s.any_) + _any_characters (str); + else if (s.parser_) + s.parser_->_characters (str); + } + else + { + if (!_characters_impl (str)) + _any_characters (str); + } + } + + template + void complex_content:: + _pre_impl () + { + context_.push (state ()); + this->_pre (); + } + + template + void complex_content:: + _post_impl () + { + this->_post (); + context_.pop (); + } + + // list_base + // + namespace bits + { + // Find first non-space character. + // + template + typename ro_string::size_type + find_ns (const C* s, + typename ro_string::size_type size, + typename ro_string::size_type pos) + { + while (pos < size && + (s[pos] == C (0x20) || s[pos] == C (0x0A) || + s[pos] == C (0x0D) || s[pos] == C (0x09))) + ++pos; + + return pos < size ? pos : ro_string::npos; + } + + // Find first space character. + // + template + typename ro_string::size_type + find_s (const C* s, + typename ro_string::size_type size, + typename ro_string::size_type pos) + { + while (pos < size && + s[pos] != C (0x20) && s[pos] != C (0x0A) && + s[pos] != C (0x0D) && s[pos] != C (0x09)) + ++pos; + + return pos < size ? pos : ro_string::npos; + } + } + + // Relevant XML Schema Part 2: Datatypes sections: 4.2.1.2, 4.3.6. + // + + template + void list_base:: + _pre_impl () + { + simple_content::_pre_impl (); + buf_.clear (); + } + + template + void list_base:: + _characters (const ro_string& s) + { + typedef typename ro_string::size_type size_type; + + const C* data (s.data ()); + size_type size (s.size ()); + + // Handle the previous chunk if we start with a ws. + // + if (!buf_.empty () && + (data[0] == C (0x20) || data[0] == C (0x0A) || + data[0] == C (0x0D) || data[0] == C (0x09))) + { + ro_string tmp (buf_); // Private copy ctor. + _xsd_parse_item (tmp); + buf_.clear (); + } + + // Traverse the data while logically collapsing spaces. + // + for (size_type i (bits::find_ns (data, size, 0)); + i != ro_string::npos;) + { + size_type j (bits::find_s (data, size, i)); + + if (j != ro_string::npos) + { + if (buf_.empty ()) + { + ro_string tmp (data + i, j - i); // Private copy ctor. + _xsd_parse_item (tmp); + } + else + { + // Assemble the first item in str from buf_ and s. + // + std::basic_string str; + str.swap (buf_); + str.append (data + i, j - i); + ro_string tmp (str); // Private copy ctor. + _xsd_parse_item (tmp); + } + + i = bits::find_ns (data, size, j); + } + else + { + // Last fragment, append it to the buf_. + // + buf_.append (data + i, size - i); + break; + } + } + } + + template + void list_base:: + _post_impl () + { + // Handle the last item. + // + if (!buf_.empty ()) + { + ro_string tmp (buf_); // Private copy ctor. + _xsd_parse_item (tmp); + } + + simple_content::_post_impl (); + } + } + } + } +} -- cgit v1.1