// file : xsd/cxx/parser/validating/parser.txx // copyright : Copyright (c) 2005-2014 Code Synthesis Tools CC // license : GNU GPL v2 + exceptions; see accompanying LICENSE file #include #include #include namespace xsd { namespace cxx { namespace parser { namespace 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 (!this->_start_element_impl (ns, name, type)) this->_unexpected_element (ns, name); } template void empty_content:: _end_element (const ro_string& ns, const ro_string& name) { if (!this->_end_element_impl (ns, name)) this->_unexpected_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_lit () || 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 (!this->_attribute_impl (ns, name, value)) this->_unexpected_attribute (ns, name, value); } template void empty_content:: _characters (const ro_string& s) { if (!this->_characters_impl (s)) this->_unexpected_characters (s); } // // template void empty_content:: _expected_element (const C* ex_ns, const C* ex_name) { throw expected_element (ex_ns, ex_name); } template void empty_content:: _expected_element (const C* ex_ns, const C* ex_name, const ro_string& en_ns, const ro_string& en_name) { throw expected_element (ex_ns, ex_name, en_ns, en_name); } template void empty_content:: _unexpected_element (const ro_string& ns, const ro_string& name) { throw unexpected_element (ns, name); } template void empty_content:: _expected_attribute (const C* ex_ns, const C* ex_name) { throw expected_attribute (ex_ns, ex_name); } template void empty_content:: _unexpected_attribute (const ro_string& ns, const ro_string& name, const ro_string&) { throw unexpected_attribute (ns, name); } template void empty_content:: _unexpected_characters (const ro_string& s) { throw unexpected_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_lit () || 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 (!this->_attribute_impl (ns, name, value)) this->_unexpected_attribute (ns, name, value); } template void simple_content:: _characters (const ro_string& str) { if (!this->_characters_impl (str)) { // Mixed content is implemented in the generated code // by overriding _characters_impl and forwarding to // _any_characters. // // Scan the string for any non-whitespace characters // (Structures, section 3.4.4, clause 1.3). // for (typename ro_string::size_type i (0), e (str.size ()); i < e; ++i) { C c (str[i]); if (c != C (0x20) && // space c != C (0x0D) && // carriage return c != C (0x09) && // tab c != C (0x0A)) this->_unexpected_characters (str); } } } template void simple_content:: _pre_impl () { this->_pre (); _pre_a_validate (); } template void simple_content:: _post_impl () { _post_a_validate (); this->_post (); } template void simple_content:: _pre_a_validate () { } template void simple_content:: _post_a_validate () { } template bool simple_content:: _attribute_impl (const ro_string& ns, const ro_string& name, const ro_string& value) { return _attribute_impl_phase_one (ns, name, value) || _attribute_impl_phase_two (ns, name, value); } template bool simple_content:: _attribute_impl_phase_one (const ro_string&, const ro_string&, const ro_string&) { return false; } template bool simple_content:: _attribute_impl_phase_two (const ro_string&, const ro_string&, const ro_string&) { return false; } // 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_) this->_start_any_element (ns, name, type); else if (s.parser_) s.parser_->_start_element (ns, name, type); } else { if (!this->_start_element_impl (ns, name, type)) this->_unexpected_element (ns, name); 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 (!this->_end_element_impl (ns, name)) assert (false); } } else { state& s (context_.top ()); if (--s.depth_ > 0) { if (s.any_) this->_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 (!this->_end_element_impl (ns, name)) this->_unexpected_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_lit () || 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; const state& s (context_.top ()); if (s.depth_ > 0) { if (s.any_) this->_any_attribute (ns, name, value); else if (s.parser_) s.parser_->_attribute (ns, name, value); } else { if (!this->_attribute_impl (ns, name, value)) this->_unexpected_attribute (ns, name, value); } } template void complex_content:: _characters (const ro_string& str) { const state& s (context_.top ()); if (s.depth_ > 0) { if (s.any_) this->_any_characters (str); else if (s.parser_) s.parser_->_characters (str); } else { if (!this->_characters_impl (str)) { // Mixed content is implemented in the generated code // by overriding _characters_impl and forwarding to // _any_characters. // // Scan the string for any non-whitespace characters // (Structures, section 3.4.4, clause 1.3). // for (typename ro_string::size_type i (0), e (str.size ()); i < e; ++i) { C c (str[i]); if (c != C (0x20) && // space c != C (0x0D) && // carriage return c != C (0x09) && // tab c != C (0x0A)) this->_unexpected_characters (str); } } } } template void complex_content:: _pre_impl () { context_.push (state ()); this->_pre (); _pre_a_validate (); _pre_e_validate (); } template void complex_content:: _post_impl () { _post_e_validate (); _post_a_validate (); this->_post (); context_.pop (); } template void complex_content:: _pre_e_validate () { } template void complex_content:: _post_e_validate () { } template void complex_content:: _pre_a_validate () { } template void complex_content:: _post_a_validate () { } template bool complex_content:: _attribute_impl (const ro_string& ns, const ro_string& name, const ro_string& value) { return _attribute_impl_phase_one (ns, name, value) || _attribute_impl_phase_two (ns, name, value); } template bool complex_content:: _attribute_impl_phase_one (const ro_string&, const ro_string&, const ro_string&) { return false; } template bool complex_content:: _attribute_impl_phase_two (const ro_string&, const ro_string&, const ro_string&) { return false; } // 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 (); } } } } }