summaryrefslogtreecommitdiff
path: root/libxsd/xsd/cxx/parser/validating/parser.txx
diff options
context:
space:
mode:
Diffstat (limited to 'libxsd/xsd/cxx/parser/validating/parser.txx')
-rw-r--r--libxsd/xsd/cxx/parser/validating/parser.txx667
1 files changed, 667 insertions, 0 deletions
diff --git a/libxsd/xsd/cxx/parser/validating/parser.txx b/libxsd/xsd/cxx/parser/validating/parser.txx
new file mode 100644
index 0000000..4cf9b7e
--- /dev/null
+++ b/libxsd/xsd/cxx/parser/validating/parser.txx
@@ -0,0 +1,667 @@
+// file : xsd/cxx/parser/validating/parser.txx
+// author : Boris Kolpackov <boris@codesynthesis.com>
+// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC
+// license : GNU GPL v2 + exceptions; see accompanying LICENSE file
+
+#include <cassert>
+
+#include <xsd/cxx/xml/bits/literals.hxx>
+#include <xsd/cxx/parser/validating/exceptions.hxx>
+
+namespace xsd
+{
+ namespace cxx
+ {
+ namespace parser
+ {
+ namespace validating
+ {
+
+ // empty_content
+ //
+
+
+ template <typename C>
+ void empty_content<C>::
+ _start_any_element (const ro_string<C>&,
+ const ro_string<C>&,
+ const ro_string<C>*)
+ {
+ }
+
+ template <typename C>
+ void empty_content<C>::
+ _end_any_element (const ro_string<C>&,
+ const ro_string<C>&)
+ {
+ }
+
+ template <typename C>
+ void empty_content<C>::
+ _any_attribute (const ro_string<C>&,
+ const ro_string<C>&,
+ const ro_string<C>&)
+ {
+ }
+
+ template <typename C>
+ void empty_content<C>::
+ _any_characters (const ro_string<C>&)
+ {
+ }
+
+ //
+ //
+ template <typename C>
+ bool empty_content<C>::
+ _start_element_impl (const ro_string<C>&,
+ const ro_string<C>&,
+ const ro_string<C>*)
+ {
+ return false;
+ }
+
+ template <typename C>
+ bool empty_content<C>::
+ _end_element_impl (const ro_string<C>&,
+ const ro_string<C>&)
+ {
+ return false;
+ }
+
+ template <typename C>
+ bool empty_content<C>::
+ _attribute_impl (const ro_string<C>&,
+ const ro_string<C>&,
+ const ro_string<C>&)
+ {
+ return false;
+ }
+
+ template <typename C>
+ bool empty_content<C>::
+ _characters_impl (const ro_string<C>&)
+ {
+ return false;
+ }
+
+ //
+ //
+ template <typename C>
+ void empty_content<C>::
+ _start_element (const ro_string<C>& ns,
+ const ro_string<C>& name,
+ const ro_string<C>* type)
+ {
+ if (!_start_element_impl (ns, name, type))
+ _unexpected_element (ns, name);
+ }
+
+ template <typename C>
+ void empty_content<C>::
+ _end_element (const ro_string<C>& ns,
+ const ro_string<C>& name)
+ {
+ if (!_end_element_impl (ns, name))
+ _unexpected_element (ns, name);
+ }
+
+ template <typename C>
+ void empty_content<C>::
+ _attribute (const ro_string<C>& ns,
+ const ro_string<C>& name,
+ const ro_string<C>& 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<C> () &&
+ (name == xml::bits::type<C> () ||
+ name == xml::bits::nil<C> () ||
+ name == xml::bits::schema_location<C> () ||
+ name == xml::bits::no_namespace_schema_location<C> ()))
+ return;
+
+ // Also some parsers (notably Xerces-C++) supplies us with
+ // namespace-prefix mapping attributes.
+ //
+ if (ns == xml::bits::xmlns_namespace<C> ())
+ return;
+
+ if (!_attribute_impl (ns, name, value))
+ _unexpected_attribute (ns, name, value);
+ }
+
+ template <typename C>
+ void empty_content<C>::
+ _characters (const ro_string<C>& s)
+ {
+ if (!_characters_impl (s))
+ _unexpected_characters (s);
+ }
+
+ //
+ //
+ template <typename C>
+ void empty_content<C>::
+ _expected_element (const C* ex_ns, const C* ex_name)
+ {
+ throw expected_element<C> (ex_ns, ex_name);
+ }
+
+ template <typename C>
+ void empty_content<C>::
+ _expected_element (const C* ex_ns,
+ const C* ex_name,
+ const ro_string<C>& en_ns,
+ const ro_string<C>& en_name)
+ {
+ throw expected_element<C> (ex_ns, ex_name, en_ns, en_name);
+ }
+
+ template <typename C>
+ void empty_content<C>::
+ _unexpected_element (const ro_string<C>& ns,
+ const ro_string<C>& name)
+ {
+ throw unexpected_element<C> (ns, name);
+ }
+
+ template <typename C>
+ void empty_content<C>::
+ _expected_attribute (const C* ex_ns, const C* ex_name)
+ {
+ throw expected_attribute<C> (ex_ns, ex_name);
+ }
+
+ template <typename C>
+ void empty_content<C>::
+ _unexpected_attribute (const ro_string<C>& ns,
+ const ro_string<C>& name,
+ const ro_string<C>&)
+ {
+ throw unexpected_attribute<C> (ns, name);
+ }
+
+ template <typename C>
+ void empty_content<C>::
+ _unexpected_characters (const ro_string<C>& s)
+ {
+ throw unexpected_characters<C> (s);
+ }
+
+
+ // simple_content
+ //
+
+ template <typename C>
+ void simple_content<C>::
+ _attribute (const ro_string<C>& ns,
+ const ro_string<C>& name,
+ const ro_string<C>& 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<C> () &&
+ (name == xml::bits::type<C> () ||
+ name == xml::bits::nil<C> () ||
+ name == xml::bits::schema_location<C> () ||
+ name == xml::bits::no_namespace_schema_location<C> ()))
+ return;
+
+ // Also some parsers (notably Xerces-C++) supplies us with
+ // namespace-prefix mapping attributes.
+ //
+ if (ns == xml::bits::xmlns_namespace<C> ())
+ return;
+
+ if (!_attribute_impl (ns, name, value))
+ _unexpected_attribute (ns, name, value);
+ }
+
+ template <typename C>
+ void simple_content<C>::
+ _characters (const ro_string<C>& str)
+ {
+ if (!_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<C>::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))
+ _unexpected_characters (str);
+ }
+ }
+ }
+
+ template <typename C>
+ void simple_content<C>::
+ _pre_impl ()
+ {
+ this->_pre ();
+ _pre_a_validate ();
+ }
+
+ template <typename C>
+ void simple_content<C>::
+ _post_impl ()
+ {
+ _post_a_validate ();
+ this->_post ();
+ }
+
+ template <typename C>
+ void simple_content<C>::
+ _pre_a_validate ()
+ {
+ }
+
+ template <typename C>
+ void simple_content<C>::
+ _post_a_validate ()
+ {
+ }
+
+ template <typename C>
+ bool simple_content<C>::
+ _attribute_impl (const ro_string<C>& ns,
+ const ro_string<C>& name,
+ const ro_string<C>& value)
+ {
+ return _attribute_impl_phase_one (ns, name, value) ||
+ _attribute_impl_phase_two (ns, name, value);
+ }
+
+ template <typename C>
+ bool simple_content<C>::
+ _attribute_impl_phase_one (const ro_string<C>&,
+ const ro_string<C>&,
+ const ro_string<C>&)
+ {
+ return false;
+ }
+
+ template <typename C>
+ bool simple_content<C>::
+ _attribute_impl_phase_two (const ro_string<C>&,
+ const ro_string<C>&,
+ const ro_string<C>&)
+ {
+ return false;
+ }
+
+
+ // complex_content
+ //
+
+
+ template <typename C>
+ void complex_content<C>::
+ _start_element (const ro_string<C>& ns,
+ const ro_string<C>& name,
+ const ro_string<C>* 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))
+ _unexpected_element (ns, name);
+ else if (s.parser_ != 0)
+ s.parser_->_pre_impl ();
+ }
+ }
+
+ template <typename C>
+ void complex_content<C>::
+ _end_element (const ro_string<C>& ns,
+ const ro_string<C>& 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))
+ _unexpected_element (ns, name);
+ }
+ }
+ }
+
+ template <typename C>
+ void complex_content<C>::
+ _attribute (const ro_string<C>& ns,
+ const ro_string<C>& name,
+ const ro_string<C>& 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<C> () &&
+ (name == xml::bits::type<C> () ||
+ name == xml::bits::nil<C> () ||
+ name == xml::bits::schema_location<C> () ||
+ name == xml::bits::no_namespace_schema_location<C> ()))
+ return;
+
+ // Also some parsers (notably Xerces-C++) supplies us with
+ // namespace-prefix mapping attributes.
+ //
+ if (ns == xml::bits::xmlns_namespace<C> ())
+ return;
+
+ const 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))
+ _unexpected_attribute (ns, name, value);
+ }
+ }
+
+ template <typename C>
+ void complex_content<C>::
+ _characters (const ro_string<C>& str)
+ {
+ const 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))
+ {
+ // 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<C>::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))
+ _unexpected_characters (str);
+ }
+ }
+ }
+ }
+
+ template <typename C>
+ void complex_content<C>::
+ _pre_impl ()
+ {
+ context_.push (state ());
+ this->_pre ();
+ _pre_a_validate ();
+ _pre_e_validate ();
+ }
+
+ template <typename C>
+ void complex_content<C>::
+ _post_impl ()
+ {
+ _post_e_validate ();
+ _post_a_validate ();
+ this->_post ();
+ context_.pop ();
+ }
+
+ template <typename C>
+ void complex_content<C>::
+ _pre_e_validate ()
+ {
+ }
+
+ template <typename C>
+ void complex_content<C>::
+ _post_e_validate ()
+ {
+ }
+
+ template <typename C>
+ void complex_content<C>::
+ _pre_a_validate ()
+ {
+ }
+
+ template <typename C>
+ void complex_content<C>::
+ _post_a_validate ()
+ {
+ }
+
+ template <typename C>
+ bool complex_content<C>::
+ _attribute_impl (const ro_string<C>& ns,
+ const ro_string<C>& name,
+ const ro_string<C>& value)
+ {
+ return _attribute_impl_phase_one (ns, name, value) ||
+ _attribute_impl_phase_two (ns, name, value);
+ }
+
+ template <typename C>
+ bool complex_content<C>::
+ _attribute_impl_phase_one (const ro_string<C>&,
+ const ro_string<C>&,
+ const ro_string<C>&)
+ {
+ return false;
+ }
+
+ template <typename C>
+ bool complex_content<C>::
+ _attribute_impl_phase_two (const ro_string<C>&,
+ const ro_string<C>&,
+ const ro_string<C>&)
+ {
+ return false;
+ }
+
+
+ // list_base
+ //
+ namespace bits
+ {
+ // Find first non-space character.
+ //
+ template <typename C>
+ typename ro_string<C>::size_type
+ find_ns (const C* s,
+ typename ro_string<C>::size_type size,
+ typename ro_string<C>::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<C>::npos;
+ }
+
+ // Find first space character.
+ //
+ template <typename C>
+ typename ro_string<C>::size_type
+ find_s (const C* s,
+ typename ro_string<C>::size_type size,
+ typename ro_string<C>::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<C>::npos;
+ }
+ }
+
+ // Relevant XML Schema Part 2: Datatypes sections: 4.2.1.2, 4.3.6.
+ //
+
+ template <typename C>
+ void list_base<C>::
+ _pre_impl ()
+ {
+ simple_content<C>::_pre_impl ();
+ buf_.clear ();
+ }
+
+ template <typename C>
+ void list_base<C>::
+ _characters (const ro_string<C>& s)
+ {
+ typedef typename ro_string<C>::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<C> 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<C>::npos;)
+ {
+ size_type j (bits::find_s (data, size, i));
+
+ if (j != ro_string<C>::npos)
+ {
+ if (buf_.empty ())
+ {
+ ro_string<C> 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<C> str;
+ str.swap (buf_);
+ str.append (data + i, j - i);
+ ro_string<C> 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 <typename C>
+ void list_base<C>::
+ _post_impl ()
+ {
+ // Handle the last item.
+ //
+ if (!buf_.empty ())
+ {
+ ro_string<C> tmp (buf_); // Private copy ctor.
+ _xsd_parse_item (tmp);
+ }
+
+ simple_content<C>::_post_impl ();
+ }
+ }
+ }
+ }
+}