aboutsummaryrefslogtreecommitdiff
path: root/examples/cxx/parser/polymorphism
diff options
context:
space:
mode:
Diffstat (limited to 'examples/cxx/parser/polymorphism')
-rw-r--r--examples/cxx/parser/polymorphism/README38
-rw-r--r--examples/cxx/parser/polymorphism/driver.cxx115
-rw-r--r--examples/cxx/parser/polymorphism/makefile71
-rw-r--r--examples/cxx/parser/polymorphism/supermen-pimpl-mixin.cxx86
-rw-r--r--examples/cxx/parser/polymorphism/supermen-pimpl-mixin.hxx69
-rw-r--r--examples/cxx/parser/polymorphism/supermen-pimpl-tiein.cxx104
-rw-r--r--examples/cxx/parser/polymorphism/supermen-pimpl-tiein.hxx81
-rw-r--r--examples/cxx/parser/polymorphism/supermen.xml26
-rw-r--r--examples/cxx/parser/polymorphism/supermen.xsd49
9 files changed, 639 insertions, 0 deletions
diff --git a/examples/cxx/parser/polymorphism/README b/examples/cxx/parser/polymorphism/README
new file mode 100644
index 0000000..0b3d749
--- /dev/null
+++ b/examples/cxx/parser/polymorphism/README
@@ -0,0 +1,38 @@
+This example shows how to handle XML Schema polymorphism features such
+as xsi:type attributes and substitution groups in the Embedded C++/Parser
+mapping. The case when xsi:type or substitution groups are used on root
+elements is covered in the polyroot examples.
+
+The example consists of the following files:
+
+supermen.xsd
+ XML Schema which describes supermen instance documents.
+
+supermen.xml
+ Sample XML instance document.
+
+supermen-pskel.hxx
+supermen-pskel.cxx
+ Parser skeletons generated by the XSD/e compiler from supermen.xsd.
+ Note the use of the --generate-polymorphic command line option.
+
+supermen-pimpl-mixin.hxx
+supermen-pimpl-mixin.cxx
+
+supermen-pimpl-tiein.hxx
+supermen-pimpl-tiein.cxx
+ Parser implementations (using either mixin or tiein parser reuse
+ style) that print the XML data to STDOUT.
+
+driver.cxx
+ Driver for the example. It first constructs a parser instance from
+ all the individual parsers found in one of supermen-pimpl-*.hxx. It
+ then invokes this parser instance to parse the input file.
+
+To run the example on the sample XML instance document simply execute:
+
+$ ./driver supermen.xml
+
+The example reads from STDIN if input file is not specified:
+
+$ ./driver <supermen.xml
diff --git a/examples/cxx/parser/polymorphism/driver.cxx b/examples/cxx/parser/polymorphism/driver.cxx
new file mode 100644
index 0000000..907be5d
--- /dev/null
+++ b/examples/cxx/parser/polymorphism/driver.cxx
@@ -0,0 +1,115 @@
+// file : examples/cxx/parser/polymorphism/driver.cxx
+// author : Boris Kolpackov <boris@codesynthesis.com>
+// copyright : not copyrighted - public domain
+
+#include <iostream>
+
+#include "supermen-pskel.hxx" // Get the configuration macros (XSDE_*).
+
+#if defined(XSDE_REUSE_STYLE_MIXIN)
+# include "supermen-pimpl-mixin.hxx"
+#elif defined(XSDE_REUSE_STYLE_TIEIN)
+# include "supermen-pimpl-tiein.hxx"
+#else
+# error this example requires mixin or tiein parser reuse support
+#endif
+
+using std::cerr;
+using std::endl;
+
+int
+main (int argc, char* argv[])
+{
+ // Check that the load in substitution and inheritance hashmaps
+ // is not too high.
+ //
+#ifndef NDEBUG
+ float load = (float) xml_schema::parser_smap_elements ();
+ load /= xml_schema::parser_smap_buckets ();
+
+ if (load > 0.8)
+ {
+ cerr << "substitution hashmap load is " << load << endl;
+ cerr << "time to increase XSDE_PARSER_SMAP_BUCKETS" << endl;
+ }
+
+#ifdef XSDE_PARSER_VALIDATION
+ load = (float) xml_schema::parser_imap_elements ();
+ load /= xml_schema::parser_imap_buckets ();
+
+ if (load > 0.8)
+ {
+ cerr << "inheritance hashmap load is " << load << endl;
+ cerr << "time to increase XSDE_PARSER_IMAP_BUCKETS" << endl;
+ }
+#endif
+#endif
+
+ const char* input;
+
+ if (argc < 2)
+ {
+ input = "STDIN";
+ cerr << "XML file not specified, reading from STDIN" << endl;
+ }
+ else
+ input = argv[1];
+
+ try
+ {
+ // Construct the parser.
+ //
+ xml_schema::string_pimpl string_p;
+ xml_schema::boolean_pimpl boolean_p;
+ xml_schema::unsigned_int_pimpl unsigned_int_p;
+
+ person_pimpl person_p;
+ superman_pimpl superman_p;
+ batman_pimpl batman_p;
+
+ xml_schema::parser_map_impl person_map (5); // 5 hashtable buckets
+ supermen_pimpl supermen_p;
+
+
+ person_p.parsers (string_p);
+ superman_p.parsers (string_p, boolean_p);
+ batman_p.parsers (string_p, boolean_p, unsigned_int_p);
+
+ // Here we are specifying several parsers that can be
+ // used to parse the person element.
+ //
+ person_map.insert (person_p);
+ person_map.insert (superman_p);
+ person_map.insert (batman_p);
+
+ supermen_p.person_parser (person_map);
+
+ // Parse the XML document. The last argument to the document's
+ // constructor indicates that we are parsing polymorphic XML
+ // documents.
+ //
+ xml_schema::document_pimpl doc_p (supermen_p, "supermen", true);
+
+ supermen_p.pre ();
+
+ if (argc < 2)
+ doc_p.parse (std::cin);
+ else
+ doc_p.parse (argv[1]);
+
+ supermen_p.post_supermen ();
+ }
+ catch (const xml_schema::parser_exception& e)
+ {
+ cerr << input << ":" << e.line () << ":" << e.column () << ": "
+ << e.text () << endl;
+ return 1;
+ }
+ catch (const std::ios_base::failure&)
+ {
+ cerr << input << ": unable to open or read failure" << endl;
+ return 1;
+ }
+
+ return 0;
+}
diff --git a/examples/cxx/parser/polymorphism/makefile b/examples/cxx/parser/polymorphism/makefile
new file mode 100644
index 0000000..c096e5a
--- /dev/null
+++ b/examples/cxx/parser/polymorphism/makefile
@@ -0,0 +1,71 @@
+# file : examples/cxx/parser/polymorphism/makefile
+# 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 $(dir $(lastword $(MAKEFILE_LIST)))../../../../build/bootstrap.make
+
+xsd := supermen.xsd
+cxx := driver.cxx
+
+ifeq ($(xsde_reuse_style),mixin)
+cxx += supermen-pimpl-mixin.cxx
+else
+cxx += supermen-pimpl-tiein.cxx
+endif
+
+obj := $(addprefix $(out_base)/,$(cxx:.cxx=.o) $(xsd:.xsd=-pskel.o))
+dep := $(obj:.o=.o.d)
+
+xsde.l := $(out_root)/libxsde/xsde/xsde.l
+xsde.l.cpp-options := $(out_root)/libxsde/xsde/xsde.l.cpp-options
+
+driver := $(out_base)/driver
+clean := $(out_base)/.clean
+
+
+# Build.
+#
+$(driver): $(obj) $(xsde.l)
+
+$(obj) $(dep): cpp_options := -I$(out_base) -I$(src_base)
+$(obj) $(dep): $(xsde.l.cpp-options)
+
+skel := $(out_base)/$(xsd:.xsd=-pskel.hxx) \
+ $(out_base)/$(xsd:.xsd=-pskel.ixx) \
+ $(out_base)/$(xsd:.xsd=-pskel.cxx)
+
+$(skel): xsde := $(out_root)/xsde/xsde
+$(skel): xsde_options += --generate-polymorphic
+$(skel): $(out_root)/xsde/xsde
+
+$(call include-dep,$(dep))
+
+# Convenience alias for default target.
+#
+.PHONY: $(out_base)/
+$(out_base)/: $(driver)
+
+
+# Clean.
+#
+.PHONY: $(clean)
+
+$(clean): $(driver).o.clean \
+ $(addsuffix .cxx.clean,$(obj)) \
+ $(addsuffix .cxx.clean,$(dep)) \
+ $(addprefix $(out_base)/,$(xsd:.xsd=-pskel.cxx.xsd.clean))
+
+
+# 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,$(scf_root)/xsde/parser/xsd-cxx.make)
+
+
+# Dependencies.
+#
+$(call import,$(src_root)/xsde/makefile)
+$(call import,$(src_root)/libxsde/xsde/makefile)
diff --git a/examples/cxx/parser/polymorphism/supermen-pimpl-mixin.cxx b/examples/cxx/parser/polymorphism/supermen-pimpl-mixin.cxx
new file mode 100644
index 0000000..e8fa8e4
--- /dev/null
+++ b/examples/cxx/parser/polymorphism/supermen-pimpl-mixin.cxx
@@ -0,0 +1,86 @@
+// file : examples/cxx/parser/polymorphism/supermen-pimpl-mixin.cxx
+// author : Boris Kolpackov <boris@codesynthesis.com>
+// copyright : not copyrighted - public domain
+//
+
+#include <iostream>
+
+#include "supermen-pimpl-mixin.hxx"
+
+using std::cout;
+using std::endl;
+
+// person_pimpl
+//
+void person_pimpl::
+pre ()
+{
+ cout << "starting to parse person" << endl;
+}
+
+void person_pimpl::
+name (const std::string& v)
+{
+ cout << "name: " << v << endl;
+}
+
+void person_pimpl::
+post_person ()
+{
+ cout << "finished parsing person" << endl
+ << endl;
+}
+
+// superman_pimpl
+//
+void superman_pimpl::
+pre ()
+{
+ cout << "strarting to parse superman" << endl;
+}
+
+void superman_pimpl::
+can_fly (bool v)
+{
+ cout << "can-fly: " << v << endl;
+}
+
+void superman_pimpl::
+post_person ()
+{
+ post_superman ();
+}
+
+void superman_pimpl::
+post_superman ()
+{
+ cout << "finished parsing superman" << endl
+ << endl;
+}
+
+// batman_pimpl
+//
+void batman_pimpl::
+pre ()
+{
+ cout << "starting to parse batman" << endl;
+}
+
+void batman_pimpl::
+wing_span (unsigned int v)
+{
+ cout << "wing-span: " << v << endl;
+}
+
+void batman_pimpl::
+post_superman ()
+{
+ post_batman ();
+}
+
+void batman_pimpl::
+post_batman ()
+{
+ cout << "finished parsing batman" << endl
+ << endl;
+}
diff --git a/examples/cxx/parser/polymorphism/supermen-pimpl-mixin.hxx b/examples/cxx/parser/polymorphism/supermen-pimpl-mixin.hxx
new file mode 100644
index 0000000..d07215e
--- /dev/null
+++ b/examples/cxx/parser/polymorphism/supermen-pimpl-mixin.hxx
@@ -0,0 +1,69 @@
+// file : examples/cxx/parser/polymorphism/supermen-pimpl-mixin.hxx
+// author : Boris Kolpackov <boris@codesynthesis.com>
+// copyright : not copyrighted - public domain
+
+#ifndef SUPERMEN_PIMPL_HXX
+#define SUPERMEN_PIMPL_HXX
+
+#include "supermen-pskel.hxx"
+
+class person_pimpl: public virtual person_pskel
+{
+public:
+ virtual void
+ pre ();
+
+ virtual void
+ name (const std::string&);
+
+ virtual void
+ post_person ();
+};
+
+class superman_pimpl: public virtual superman_pskel,
+ public person_pimpl
+{
+public:
+ virtual void
+ pre ();
+
+ virtual void
+ can_fly (bool);
+
+ // By default, post_superman() calls post_person(). In case of
+ // polymorphic parsing we want the opposite: post_person() calls
+ // post_superman().
+ //
+ virtual void
+ post_person ();
+
+ virtual void
+ post_superman ();
+};
+
+class batman_pimpl: public virtual batman_pskel,
+ public superman_pimpl
+{
+public:
+ virtual void
+ pre ();
+
+ virtual void
+ wing_span (unsigned int);
+
+ // By default, post_batman() calls post_superman(). In case of
+ // polymorphic parsing we want the opposite: post_superman()
+ // calls post_batman().
+ //
+ virtual void
+ post_superman ();
+
+ virtual void
+ post_batman ();
+};
+
+class supermen_pimpl: public virtual supermen_pskel
+{
+};
+
+#endif // SUPERMEN_PIMPL_HXX
diff --git a/examples/cxx/parser/polymorphism/supermen-pimpl-tiein.cxx b/examples/cxx/parser/polymorphism/supermen-pimpl-tiein.cxx
new file mode 100644
index 0000000..cb9ece3
--- /dev/null
+++ b/examples/cxx/parser/polymorphism/supermen-pimpl-tiein.cxx
@@ -0,0 +1,104 @@
+// file : examples/cxx/parser/polymorphism/supermen-pimpl-tiein.cxx
+// author : Boris Kolpackov <boris@codesynthesis.com>
+// copyright : not copyrighted - public domain
+//
+
+#include <iostream>
+
+#include "supermen-pimpl-tiein.hxx"
+
+using std::cout;
+using std::endl;
+
+// person_pimpl
+//
+void person_pimpl::
+pre ()
+{
+ cout << "starting to parse person" << endl;
+}
+
+void person_pimpl::
+name (const std::string& v)
+{
+ cout << "name: " << v << endl;
+}
+
+void person_pimpl::
+post_person ()
+{
+ cout << "finished parsing person" << endl
+ << endl;
+}
+
+// superman_pimpl
+//
+superman_pimpl::
+superman_pimpl ()
+ : superman_pskel (&base_impl_)
+{
+}
+
+void superman_pimpl::
+pre ()
+{
+ cout << "starting to parse superman" << endl;
+}
+
+void superman_pimpl::
+can_fly (bool v)
+{
+ cout << "can-fly: " << v << endl;
+}
+
+void superman_pimpl::
+post_person ()
+{
+ post_superman ();
+}
+
+void superman_pimpl::
+post_superman ()
+{
+ cout << "finished parsing superman" << endl
+ << endl;
+}
+
+// batman_pimpl
+//
+batman_pimpl::
+batman_pimpl ()
+ : batman_pskel (&base_impl_)
+{
+}
+
+void batman_pimpl::
+pre ()
+{
+ cout << "starting to parse batman" << endl;
+}
+
+void batman_pimpl::
+wing_span (unsigned int v)
+{
+ cout << "wing-span: " << v << endl;
+}
+
+void batman_pimpl::
+post_person ()
+{
+ post_superman ();
+}
+
+void batman_pimpl::
+post_superman ()
+{
+ post_batman ();
+}
+
+void batman_pimpl::
+post_batman ()
+{
+ cout << "finished parsing batman" << endl
+ << endl;
+}
diff --git a/examples/cxx/parser/polymorphism/supermen-pimpl-tiein.hxx b/examples/cxx/parser/polymorphism/supermen-pimpl-tiein.hxx
new file mode 100644
index 0000000..b8acd74
--- /dev/null
+++ b/examples/cxx/parser/polymorphism/supermen-pimpl-tiein.hxx
@@ -0,0 +1,81 @@
+// file : examples/cxx/parser/polymorphism/supermen-pimpl-tiein.hxx
+// author : Boris Kolpackov <boris@codesynthesis.com>
+// copyright : not copyrighted - public domain
+
+#ifndef SUPERMEN_PIMPL_HXX
+#define SUPERMEN_PIMPL_HXX
+
+#include "supermen-pskel.hxx"
+
+class person_pimpl: public person_pskel
+{
+public:
+ virtual void
+ pre ();
+
+ virtual void
+ name (const std::string&);
+
+ virtual void
+ post_person ();
+};
+
+class superman_pimpl: public superman_pskel
+{
+public:
+ superman_pimpl ();
+
+ virtual void
+ pre ();
+
+ virtual void
+ can_fly (bool);
+
+ // By default, post_superman() calls post_person(). In case of
+ // polymorphic parsing we want the opposite: post_person() calls
+ // post_superman().
+ //
+ virtual void
+ post_person ();
+
+ virtual void
+ post_superman ();
+
+private:
+ person_pimpl base_impl_;
+};
+
+class batman_pimpl: public batman_pskel
+{
+public:
+ batman_pimpl ();
+
+ virtual void
+ pre ();
+
+ virtual void
+ wing_span (unsigned int);
+
+ // By default, post_batman() calls post_superman() which calls
+ // post_person(). In case of polymorphic parsing we want the
+ // opposite: post_person() calls post_superman() which calls
+ // post_batman().
+ //
+ virtual void
+ post_person ();
+
+ virtual void
+ post_superman ();
+
+ virtual void
+ post_batman ();
+
+private:
+ superman_pimpl base_impl_;
+};
+
+class supermen_pimpl: public virtual supermen_pskel
+{
+};
+
+#endif // SUPERMEN_PIMPL_HXX
diff --git a/examples/cxx/parser/polymorphism/supermen.xml b/examples/cxx/parser/polymorphism/supermen.xml
new file mode 100644
index 0000000..2d73c44
--- /dev/null
+++ b/examples/cxx/parser/polymorphism/supermen.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0"?>
+
+<!--
+
+file : examples/cxx/parser/polymorphism/supermen.xml
+author : Boris Kolpackov <boris@codesynthesis.com>
+copyright : not copyrighted - public domain
+
+-->
+
+<supermen xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:noNamespaceSchemaLocation="supermen.xsd">
+
+ <person>
+ <name>John Doe</name>
+ </person>
+
+ <superman can-fly="false">
+ <name>James "007" Bond</name>
+ </superman>
+
+ <superman can-fly="true" wing-span="10" xsi:type="batman">
+ <name>Bruce Wayne</name>
+ </superman>
+
+</supermen>
diff --git a/examples/cxx/parser/polymorphism/supermen.xsd b/examples/cxx/parser/polymorphism/supermen.xsd
new file mode 100644
index 0000000..83a7aac
--- /dev/null
+++ b/examples/cxx/parser/polymorphism/supermen.xsd
@@ -0,0 +1,49 @@
+<?xml version="1.0"?>
+
+<!--
+
+file : examples/cxx/parser/polymorphism/supermen.xsd
+author : Boris Kolpackov <boris@codesynthesis.com>
+copyright : not copyrighted - public domain
+
+-->
+
+<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema">
+
+ <xsd:complexType name="person">
+ <xsd:sequence>
+ <xsd:element name="name" type="xsd:string"/>
+ </xsd:sequence>
+ </xsd:complexType>
+
+ <!-- substitution group root -->
+ <xsd:element name="person" type="person"/>
+
+
+ <xsd:complexType name="superman">
+ <xsd:complexContent>
+ <xsd:extension base="person">
+ <xsd:attribute name="can-fly" type="xsd:boolean" use="required"/>
+ </xsd:extension>
+ </xsd:complexContent>
+ </xsd:complexType>
+
+ <xsd:element name="superman" type="superman" substitutionGroup="person"/>
+
+ <xsd:complexType name="batman">
+ <xsd:complexContent>
+ <xsd:extension base="superman">
+ <xsd:attribute name="wing-span" type="xsd:unsignedInt" use="required"/>
+ </xsd:extension>
+ </xsd:complexContent>
+ </xsd:complexType>
+
+ <xsd:complexType name="supermen">
+ <xsd:sequence>
+ <xsd:element ref="person" maxOccurs="unbounded"/>
+ </xsd:sequence>
+ </xsd:complexType>
+
+ <xsd:element name="supermen" type="supermen"/>
+
+</xsd:schema>