aboutsummaryrefslogtreecommitdiff
path: root/examples/cxx/serializer
diff options
context:
space:
mode:
Diffstat (limited to 'examples/cxx/serializer')
-rw-r--r--examples/cxx/serializer/README20
-rw-r--r--examples/cxx/serializer/hello/README25
-rw-r--r--examples/cxx/serializer/hello/driver.cxx90
-rw-r--r--examples/cxx/serializer/hello/hello.xsd22
-rw-r--r--examples/cxx/serializer/hello/makefile64
-rw-r--r--examples/cxx/serializer/library/README44
-rw-r--r--examples/cxx/serializer/library/driver.cxx140
-rw-r--r--examples/cxx/serializer/library/library-simpl-mixin.cxx184
-rw-r--r--examples/cxx/serializer/library/library-simpl-mixin.hxx138
-rw-r--r--examples/cxx/serializer/library/library-simpl-tiein.cxx208
-rw-r--r--examples/cxx/serializer/library/library-simpl-tiein.hxx154
-rw-r--r--examples/cxx/serializer/library/library.hxx270
-rw-r--r--examples/cxx/serializer/library/library.map22
-rw-r--r--examples/cxx/serializer/library/library.xsd79
-rw-r--r--examples/cxx/serializer/library/makefile72
-rw-r--r--examples/cxx/serializer/makefile49
-rw-r--r--examples/cxx/serializer/minimal/README47
-rw-r--r--examples/cxx/serializer/minimal/driver.cxx139
-rw-r--r--examples/cxx/serializer/minimal/makefile66
-rw-r--r--examples/cxx/serializer/minimal/people-simpl-mixin.hxx82
-rw-r--r--examples/cxx/serializer/minimal/people-simpl-tiein.hxx90
-rw-r--r--examples/cxx/serializer/minimal/people.hxx30
-rw-r--r--examples/cxx/serializer/minimal/people.map9
-rw-r--r--examples/cxx/serializer/minimal/people.xsd37
-rw-r--r--examples/cxx/serializer/polymorphism/README44
-rw-r--r--examples/cxx/serializer/polymorphism/driver.cxx120
-rw-r--r--examples/cxx/serializer/polymorphism/makefile73
-rw-r--r--examples/cxx/serializer/polymorphism/supermen-simpl-mixin.cxx83
-rw-r--r--examples/cxx/serializer/polymorphism/supermen-simpl-mixin.hxx51
-rw-r--r--examples/cxx/serializer/polymorphism/supermen-simpl-tiein.cxx108
-rw-r--r--examples/cxx/serializer/polymorphism/supermen-simpl-tiein.hxx69
-rw-r--r--examples/cxx/serializer/polymorphism/supermen.hxx129
-rw-r--r--examples/cxx/serializer/polymorphism/supermen.map10
-rw-r--r--examples/cxx/serializer/polymorphism/supermen.xsd49
-rw-r--r--examples/cxx/serializer/polyroot/README46
-rw-r--r--examples/cxx/serializer/polyroot/driver.cxx142
-rw-r--r--examples/cxx/serializer/polyroot/makefile73
-rw-r--r--examples/cxx/serializer/polyroot/supermen-simpl-mixin.cxx35
-rw-r--r--examples/cxx/serializer/polyroot/supermen-simpl-mixin.hxx35
-rw-r--r--examples/cxx/serializer/polyroot/supermen-simpl-tiein.cxx59
-rw-r--r--examples/cxx/serializer/polyroot/supermen-simpl-tiein.hxx53
-rw-r--r--examples/cxx/serializer/polyroot/supermen.hxx129
-rw-r--r--examples/cxx/serializer/polyroot/supermen.map9
-rw-r--r--examples/cxx/serializer/polyroot/supermen.xsd41
-rw-r--r--examples/cxx/serializer/wildcard/README37
-rw-r--r--examples/cxx/serializer/wildcard/driver.cxx410
-rw-r--r--examples/cxx/serializer/wildcard/email.hxx194
-rw-r--r--examples/cxx/serializer/wildcard/email.map12
-rw-r--r--examples/cxx/serializer/wildcard/email.xsd51
-rw-r--r--examples/cxx/serializer/wildcard/makefile66
50 files changed, 4209 insertions, 0 deletions
diff --git a/examples/cxx/serializer/README b/examples/cxx/serializer/README
new file mode 100644
index 0000000..fa71ea3
--- /dev/null
+++ b/examples/cxx/serializer/README
@@ -0,0 +1,20 @@
+This directory contains a number of examples that show how to
+use the Embedded C++/Serializer mapping. The following list
+gives an overview of each example. See the README files in
+example directories for more information on each example.
+
+hello
+ A simple "Hello, world!" example that shows how to serialize
+ XML documents.
+
+library
+ Shows how to handle more complex data structures and serialize
+ a custom in-memory object model.
+
+minimal
+ This example is a minimal serializer implementation that is
+ intended to work without STL, iostream, or C++ exceptions.
+
+wildcard
+ Shows how to serialize XML data matched by XML Schema wildcards
+ (any and anyAttribute).
diff --git a/examples/cxx/serializer/hello/README b/examples/cxx/serializer/hello/README
new file mode 100644
index 0000000..a560fac
--- /dev/null
+++ b/examples/cxx/serializer/hello/README
@@ -0,0 +1,25 @@
+This is a "Hello, world!" example that shows how to use the
+Embedded C++/Serializer mapping to serialize XML documents.
+
+The example consists of the following files:
+
+hello.xsd
+ XML Schema which describes "hello" instance documents.
+
+hello-sskel.hxx
+hello-sskel.ixx
+hello-sskel.cxx
+ Serializer skeletons generated by XSD/e from hello.xsd.
+
+driver.cxx
+ A serializer implementation and a driver for the example.
+ The serializer implementation simply creates an XML
+ document with pre-defined data. The driver first constructs
+ a serializer instance from the serializer implementation
+ mentioned above and a couple of predefined serializers for
+ the XML Schema built-in types. In then invokes this serializer
+ instance to write the XML document to STDOUT.
+
+To run the example simply execute:
+
+$ ./driver
diff --git a/examples/cxx/serializer/hello/driver.cxx b/examples/cxx/serializer/hello/driver.cxx
new file mode 100644
index 0000000..e895add
--- /dev/null
+++ b/examples/cxx/serializer/hello/driver.cxx
@@ -0,0 +1,90 @@
+// file : examples/cxx/serializer/hello/driver.cxx
+// author : Boris Kolpackov <boris@codesynthesis.com>
+// copyright : not copyrighted - public domain
+
+#include <string>
+#include <vector>
+#include <iostream>
+
+#include "hello-sskel.hxx"
+
+using namespace std;
+
+struct hello_simpl: hello_sskel
+{
+ hello_simpl ()
+ {
+ names_.push_back ("sun");
+ names_.push_back ("moon");
+ names_.push_back ("world");
+ }
+
+ virtual void
+ pre ()
+ {
+ i_ = names_.begin ();
+ }
+
+ virtual string
+ greeting ()
+ {
+ return "Hello";
+ }
+
+ virtual bool
+ name_next ()
+ {
+ return i_ != names_.end ();
+ }
+
+ virtual string
+ name ()
+ {
+ return *i_++;
+ }
+
+private:
+ typedef vector<string> names;
+
+ names names_;
+ names::iterator i_;
+};
+
+
+int
+main ()
+{
+ try
+ {
+ // Construct the serializer.
+ //
+ xml_schema::string_simpl string_s;
+ hello_simpl hello_s;
+
+ hello_s.greeting_serializer (string_s);
+ hello_s.name_serializer (string_s);
+
+
+ // Create the XML instance document. The second argument to the
+ // document's constructor is the document's root element name.
+ //
+ xml_schema::document_simpl doc_s (hello_s, "hello");
+ doc_s.add_no_namespace_schema ("hello.xsd");
+
+ hello_s.pre ();
+ doc_s.serialize (cout);
+ hello_s.post ();
+ }
+ catch (const xml_schema::serializer_exception& e)
+ {
+ cerr << "error: " << e.text () << endl;
+ return 1;
+ }
+ catch (const std::ios_base::failure&)
+ {
+ cerr << "error: write failure" << endl;
+ return 1;
+ }
+
+ return 0;
+}
diff --git a/examples/cxx/serializer/hello/hello.xsd b/examples/cxx/serializer/hello/hello.xsd
new file mode 100644
index 0000000..d2affb5
--- /dev/null
+++ b/examples/cxx/serializer/hello/hello.xsd
@@ -0,0 +1,22 @@
+<?xml version="1.0"?>
+
+<!--
+
+file : examples/cxx/serializer/hello/hello.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="hello">
+ <xsd:sequence>
+ <xsd:element name="greeting" type="xsd:string"/>
+ <xsd:element name="name" type="xsd:string" maxOccurs="unbounded"/>
+ </xsd:sequence>
+ </xsd:complexType>
+
+ <xsd:element name="hello" type="hello"/>
+
+</xsd:schema>
diff --git a/examples/cxx/serializer/hello/makefile b/examples/cxx/serializer/hello/makefile
new file mode 100644
index 0000000..c2721bb
--- /dev/null
+++ b/examples/cxx/serializer/hello/makefile
@@ -0,0 +1,64 @@
+# file : examples/cxx/serializer/hello/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 := hello.xsd
+cxx := driver.cxx
+
+obj := $(addprefix $(out_base)/,$(cxx:.cxx=.o) $(xsd:.xsd=-sskel.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)
+$(obj) $(dep): $(xsde.l.cpp-options)
+
+skel := $(out_base)/$(xsd:.xsd=-sskel.hxx) \
+ $(out_base)/$(xsd:.xsd=-sskel.ixx) \
+ $(out_base)/$(xsd:.xsd=-sskel.cxx)
+
+$(skel): xsde := $(out_root)/xsde/xsde
+$(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=-sskel.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/serializer/xsd-cxx.make)
+
+
+# Dependencies.
+#
+$(call import,$(src_root)/xsde/makefile)
+$(call import,$(src_root)/libxsde/xsde/makefile)
diff --git a/examples/cxx/serializer/library/README b/examples/cxx/serializer/library/README
new file mode 100644
index 0000000..82ca09c
--- /dev/null
+++ b/examples/cxx/serializer/library/README
@@ -0,0 +1,44 @@
+This example shows how to use the Embedded C++/Serializer
+mapping to create XML documents from a custom in-memory
+object model.
+
+The example consists of the following files:
+
+library.xsd
+ XML Schema which describes a library of books.
+
+library.hxx
+ Types that describe a library of books in C++. These are
+ hand-written.
+
+library.map
+ Type map. It maps XML Schema types defined in library.xsd
+ to C++ types defined in library.hxx.
+
+library-sskel.hxx
+library-sskel.ixx
+library-sskel.cxx
+ Serializer skeletons generated by XSD/e from library.xsd
+ and library.map.
+
+library-simpl-mixin.hxx
+library-simpl-mixin.cxx
+
+library-simpl-tiein.hxx
+library-simpl-tiein.cxx
+ Serializer implementations (using either mixin or tiein
+ parser reuse style) that serialize the custom in-memory
+ object model to XML. These are hand-written implementations
+ of the serializer skeletons defined in library-sskel.hxx.
+
+driver.cxx
+ Driver for the example. It first constructs a sample
+ object model using the types from library.hxx. It then
+ creates a serializer instance using all the individual
+ serializers found in one of library-simpl-*.hxx. Finally,
+ it invokes this serializer instance to serialize the sample
+ object model to an XML document which is printed to STDOUT.
+
+To run the example simply execute:
+
+$ ./driver
diff --git a/examples/cxx/serializer/library/driver.cxx b/examples/cxx/serializer/library/driver.cxx
new file mode 100644
index 0000000..2790028
--- /dev/null
+++ b/examples/cxx/serializer/library/driver.cxx
@@ -0,0 +1,140 @@
+// file : examples/cxx/serializer/library/driver.cxx
+// author : Boris Kolpackov <boris@codesynthesis.com>
+// copyright : not copyrighted - public domain
+
+#include <iostream>
+
+#include "library.hxx"
+
+#include "library-sskel.hxx" // Get the configuration macros (XSDE_*).
+
+#if defined(XSDE_REUSE_STYLE_MIXIN)
+# include "library-simpl-mixin.hxx"
+#elif defined(XSDE_REUSE_STYLE_TIEIN)
+# include "library-simpl-tiein.hxx"
+#else
+# error this example requires mixin or tiein serializer reuse support
+#endif
+
+using std::cerr;
+using std::endl;
+
+int
+main ()
+{
+ try
+ {
+ using namespace library;
+
+ // Create a sample library catalog.
+ //
+ catalog cat;
+
+ {
+ book b (679760806,
+ title ("The Master and Margarita"),
+ fiction,
+ false,
+ "MM");
+
+ author a ("Mikhail Bulgakov", "1891-05-15");
+ a.died ("1940-03-10");
+ a.recommends ("WP");
+
+ b.author ().push_back (a);
+
+ cat.push_back (b);
+ }
+
+ {
+ book b (679600841,
+ title ("War and Peace"),
+ history,
+ true,
+ "WP");
+
+ author a ("Leo Tolstoy", "1828-09-09");
+ a.died ("1910-11-20");
+ a.recommends ("CP");
+
+ b.author ().push_back (a);
+
+ cat.push_back (b);
+ }
+
+ {
+ book b (679420290,
+ title ("Crime and Punishment"),
+ philosophy,
+ false,
+ "CP");
+
+ author a ("Fyodor Dostoevsky", "1821-11-11");
+ a.died ("1881-02-09");
+
+ b.author ().push_back (a);
+
+ cat.push_back (b);
+ }
+
+
+ // Construct the serializer.
+ //
+ xml_schema::id_simpl id_s;
+ xml_schema::idref_simpl idref_s;
+ xml_schema::string_simpl string_s;
+ xml_schema::boolean_simpl boolean_s;
+
+ isbn_simpl isbn_s;
+
+ title_simpl title_s;
+ title_s.lang_serializer (string_s);
+
+ genre_simpl genre_s;
+
+ author_simpl author_s;
+ author_s.serializers (string_s, // name
+ string_s, // born
+ string_s, // died
+ idref_s); // recommends
+
+ book_simpl book_s;
+ book_s.serializers (boolean_s, // available
+ id_s, // id
+ isbn_s, // isbn
+ title_s, // title
+ genre_s, // genre
+ author_s); // author
+
+
+ catalog_simpl catalog_s;
+ catalog_s.book_serializer (book_s);
+
+
+ // Create the XML instance document.
+ //
+ xml_schema::document_simpl doc_s (
+ catalog_s,
+ "http://www.codesynthesis.com/library", // root element namespace
+ "catalog"); // root element name
+
+ doc_s.add_prefix ("lib", "http://www.codesynthesis.com/library");
+ doc_s.add_schema ("http://www.codesynthesis.com/library", "library.xsd");
+
+ catalog_s.pre (cat);
+ doc_s.serialize (std::cout);
+ catalog_s.post ();
+ }
+ catch (const xml_schema::serializer_exception& e)
+ {
+ cerr << "error: " << e.text () << endl;
+ return 1;
+ }
+ catch (const std::ios_base::failure&)
+ {
+ cerr << "error: write failure" << endl;
+ return 1;
+ }
+
+ return 0;
+}
diff --git a/examples/cxx/serializer/library/library-simpl-mixin.cxx b/examples/cxx/serializer/library/library-simpl-mixin.cxx
new file mode 100644
index 0000000..7e82fe6
--- /dev/null
+++ b/examples/cxx/serializer/library/library-simpl-mixin.cxx
@@ -0,0 +1,184 @@
+// file : examples/cxx/serializer/library/library-simpl-mixin.cxx
+// author : Boris Kolpackov <boris@codesynthesis.com>
+// copyright : not copyrighted - public domain
+
+#include "library-simpl-mixin.hxx"
+
+namespace library
+{
+ using namespace xml_schema;
+
+ // isbn_simpl
+ //
+ void isbn_simpl::
+ pre (isbn n)
+ {
+ unsigned_int_simpl::pre (n);
+ }
+
+ // title_simpl
+ //
+ void title_simpl::
+ pre (const title& t)
+ {
+ string_simpl::pre (t);
+ title_ = &t;
+ }
+
+ bool title_simpl::
+ lang_present ()
+ {
+ return !title_->lang ().empty ();
+ }
+
+ std::string title_simpl::
+ lang ()
+ {
+ return title_->lang ();
+ }
+
+ // genre_simpl
+ //
+ const char* genre_strings[] =
+ {
+ "romance",
+ "fiction",
+ "horror",
+ "history",
+ "philosophy"
+ };
+
+ void genre_simpl::
+ pre (genre g)
+ {
+ string_simpl::pre (genre_strings[g]);
+ }
+
+ // person_simpl
+ //
+ void person_simpl::
+ pre (const person& p)
+ {
+ person_ = &p;
+ }
+
+ std::string person_simpl::
+ name ()
+ {
+ return person_->name ();
+ }
+
+ std::string person_simpl::
+ born ()
+ {
+ return person_->born ();
+ }
+
+ bool person_simpl::
+ died_present ()
+ {
+ return !person_->died ().empty ();
+ }
+
+ std::string person_simpl::
+ died ()
+ {
+ return person_->died ();
+ }
+
+ // author_simpl
+ //
+ void author_simpl::
+ pre (const author& a)
+ {
+ person_simpl::pre (a);
+ author_ = &a;
+ }
+
+ bool author_simpl::
+ recommends_present ()
+ {
+ return !author_->recommends ().empty ();
+ }
+
+ std::string author_simpl::
+ recommends ()
+ {
+ return author_->recommends ();
+ }
+
+ // book_simpl
+ //
+
+ void book_simpl::
+ pre (const book& b)
+ {
+ book_ = &b;
+ ai_ = b.author ().begin ();
+ }
+
+ library::isbn book_simpl::
+ isbn ()
+ {
+ return book_->isbn ();
+ }
+
+ const library::title& book_simpl::
+ title ()
+ {
+ return book_->title ();
+ }
+
+
+ library::genre book_simpl::
+ genre ()
+ {
+ return book_->genre ();
+ }
+
+ bool book_simpl::
+ author_next ()
+ {
+ return ai_ != book_->author ().end ();
+ }
+
+ const library::author& book_simpl::
+ author ()
+ {
+ return *ai_++;
+ }
+
+ bool book_simpl::
+ available ()
+ {
+ return book_->available ();
+ }
+
+ std::string book_simpl::
+ id ()
+ {
+ return book_->id ();
+ }
+
+ // catalog_simpl
+ //
+ void catalog_simpl::
+ pre (const catalog& c)
+ {
+ catalog_ = &c;
+ ci_ = c.begin ();
+ }
+
+ bool catalog_simpl::
+ book_next ()
+ {
+ return ci_ != catalog_->end ();
+ }
+
+ const library::book& catalog_simpl::
+ book ()
+ {
+ return *ci_++;
+ }
+}
+
diff --git a/examples/cxx/serializer/library/library-simpl-mixin.hxx b/examples/cxx/serializer/library/library-simpl-mixin.hxx
new file mode 100644
index 0000000..c4438d4
--- /dev/null
+++ b/examples/cxx/serializer/library/library-simpl-mixin.hxx
@@ -0,0 +1,138 @@
+// file : examples/cxx/serializer/library/library-simpl-mixin.hxx
+// author : Boris Kolpackov <boris@codesynthesis.com>
+// copyright : not copyrighted - public domain
+
+#ifndef LIBRARY_SIMPL_HXX
+#define LIBRARY_SIMPL_HXX
+
+#include "library.hxx"
+#include "library-sskel.hxx"
+
+namespace library
+{
+ //
+ //
+ struct isbn_simpl: virtual isbn_sskel, xml_schema::unsigned_int_simpl
+ {
+ virtual void
+ pre (isbn);
+ };
+
+ //
+ //
+ struct title_simpl: virtual title_sskel, xml_schema::string_simpl
+ {
+ virtual void
+ pre (const title&);
+
+ virtual bool
+ lang_present ();
+
+ virtual std::string
+ lang ();
+
+ private:
+ const title* title_;
+ };
+
+ //
+ //
+ struct genre_simpl: virtual genre_sskel, xml_schema::string_simpl
+ {
+ virtual void
+ pre (genre);
+ };
+
+ //
+ //
+ struct person_simpl: virtual person_sskel
+ {
+ virtual void
+ pre (const person&);
+
+ virtual std::string
+ name ();
+
+ virtual std::string
+ born ();
+
+ virtual bool
+ died_present ();
+
+ virtual std::string
+ died ();
+
+ private:
+ const person* person_;
+ };
+
+ //
+ //
+ struct author_simpl: virtual author_sskel, person_simpl
+ {
+ virtual void
+ pre (const author&);
+
+ virtual bool
+ recommends_present ();
+
+ virtual std::string
+ recommends ();
+
+ private:
+ const author* author_;
+ };
+
+ //
+ //
+ struct book_simpl: virtual book_sskel
+ {
+ virtual void
+ pre (const book&);
+
+ virtual library::isbn
+ isbn ();
+
+ virtual const library::title&
+ title ();
+
+ virtual library::genre
+ genre ();
+
+ virtual bool
+ author_next ();
+
+ virtual const library::author&
+ author ();
+
+ virtual bool
+ available ();
+
+ virtual std::string
+ id ();
+
+ private:
+ const book* book_;
+ book::authors::const_iterator ai_;
+ };
+
+ //
+ //
+ struct catalog_simpl: virtual catalog_sskel
+ {
+ virtual void
+ pre (const catalog&);
+
+ virtual bool
+ book_next ();
+
+ virtual const library::book&
+ book ();
+
+ private:
+ const catalog* catalog_;
+ catalog::const_iterator ci_;
+ };
+}
+
+#endif // LIBRARY_SIMPL_HXX
diff --git a/examples/cxx/serializer/library/library-simpl-tiein.cxx b/examples/cxx/serializer/library/library-simpl-tiein.cxx
new file mode 100644
index 0000000..91a5c23
--- /dev/null
+++ b/examples/cxx/serializer/library/library-simpl-tiein.cxx
@@ -0,0 +1,208 @@
+// file : examples/cxx/serializer/library/library-simpl-tiein.cxx
+// author : Boris Kolpackov <boris@codesynthesis.com>
+// copyright : not copyrighted - public domain
+
+#include "library-simpl-tiein.hxx"
+
+namespace library
+{
+ using namespace xml_schema;
+
+ // isbn_simpl
+ //
+ isbn_simpl::
+ isbn_simpl ()
+ : isbn_sskel (&base_impl_)
+ {
+ }
+
+ void isbn_simpl::
+ pre (isbn n)
+ {
+ base_impl_.pre (n);
+ }
+
+ // title_simpl
+ //
+ title_simpl::
+ title_simpl ()
+ : title_sskel (&base_impl_)
+ {
+ }
+
+ void title_simpl::
+ pre (const title& t)
+ {
+ base_impl_.pre (t);
+ title_ = &t;
+ }
+
+ bool title_simpl::
+ lang_present ()
+ {
+ return !title_->lang ().empty ();
+ }
+
+ std::string title_simpl::
+ lang ()
+ {
+ return title_->lang ();
+ }
+
+ // genre_simpl
+ //
+ genre_simpl::
+ genre_simpl ()
+ : genre_sskel (&base_impl_)
+ {
+ }
+
+ const char* genre_strings[] =
+ {
+ "romance",
+ "fiction",
+ "horror",
+ "history",
+ "philosophy"
+ };
+
+ void genre_simpl::
+ pre (genre g)
+ {
+ base_impl_.pre (genre_strings[g]);
+ }
+
+ // person_simpl
+ //
+ void person_simpl::
+ pre (const person& p)
+ {
+ person_ = &p;
+ }
+
+ std::string person_simpl::
+ name ()
+ {
+ return person_->name ();
+ }
+
+ std::string person_simpl::
+ born ()
+ {
+ return person_->born ();
+ }
+
+ bool person_simpl::
+ died_present ()
+ {
+ return !person_->died ().empty ();
+ }
+
+ std::string person_simpl::
+ died ()
+ {
+ return person_->died ();
+ }
+
+ // author_simpl
+ //
+ author_simpl::
+ author_simpl ()
+ : author_sskel (&base_impl_)
+ {
+ }
+
+ void author_simpl::
+ pre (const author& a)
+ {
+ base_impl_.pre (a);
+ author_ = &a;
+ }
+
+ bool author_simpl::
+ recommends_present ()
+ {
+ return !author_->recommends ().empty ();
+ }
+
+ std::string author_simpl::
+ recommends ()
+ {
+ return author_->recommends ();
+ }
+
+ // book_simpl
+ //
+
+ void book_simpl::
+ pre (const book& b)
+ {
+ book_ = &b;
+ ai_ = b.author ().begin ();
+ }
+
+ library::isbn book_simpl::
+ isbn ()
+ {
+ return book_->isbn ();
+ }
+
+ const library::title& book_simpl::
+ title ()
+ {
+ return book_->title ();
+ }
+
+
+ library::genre book_simpl::
+ genre ()
+ {
+ return book_->genre ();
+ }
+
+ bool book_simpl::
+ author_next ()
+ {
+ return ai_ != book_->author ().end ();
+ }
+
+ const library::author& book_simpl::
+ author ()
+ {
+ return *ai_++;
+ }
+
+ bool book_simpl::
+ available ()
+ {
+ return book_->available ();
+ }
+
+ std::string book_simpl::
+ id ()
+ {
+ return book_->id ();
+ }
+
+ // catalog_simpl
+ //
+ void catalog_simpl::
+ pre (const catalog& c)
+ {
+ catalog_ = &c;
+ ci_ = c.begin ();
+ }
+
+ bool catalog_simpl::
+ book_next ()
+ {
+ return ci_ != catalog_->end ();
+ }
+
+ const library::book& catalog_simpl::
+ book ()
+ {
+ return *ci_++;
+ }
+}
+
diff --git a/examples/cxx/serializer/library/library-simpl-tiein.hxx b/examples/cxx/serializer/library/library-simpl-tiein.hxx
new file mode 100644
index 0000000..15abe74
--- /dev/null
+++ b/examples/cxx/serializer/library/library-simpl-tiein.hxx
@@ -0,0 +1,154 @@
+// file : examples/cxx/serializer/library/library-simpl-tiein.hxx
+// author : Boris Kolpackov <boris@codesynthesis.com>
+// copyright : not copyrighted - public domain
+
+#ifndef LIBRARY_SIMPL_HXX
+#define LIBRARY_SIMPL_HXX
+
+#include "library.hxx"
+#include "library-sskel.hxx"
+
+namespace library
+{
+ //
+ //
+ struct isbn_simpl: isbn_sskel
+ {
+ isbn_simpl ();
+
+ virtual void
+ pre (isbn);
+
+ private:
+ xml_schema::unsigned_int_simpl base_impl_;
+ };
+
+ //
+ //
+ struct title_simpl: title_sskel
+ {
+ title_simpl ();
+
+ virtual void
+ pre (const title&);
+
+ virtual bool
+ lang_present ();
+
+ virtual std::string
+ lang ();
+
+ private:
+ xml_schema::string_simpl base_impl_;
+ const title* title_;
+ };
+
+ //
+ //
+ struct genre_simpl: genre_sskel
+ {
+ genre_simpl ();
+
+ virtual void
+ pre (genre);
+
+ private:
+ xml_schema::string_simpl base_impl_;
+ };
+
+ //
+ //
+ struct person_simpl: person_sskel
+ {
+ virtual void
+ pre (const person&);
+
+ virtual std::string
+ name ();
+
+ virtual std::string
+ born ();
+
+ virtual bool
+ died_present ();
+
+ virtual std::string
+ died ();
+
+ private:
+ const person* person_;
+ };
+
+ //
+ //
+ struct author_simpl: author_sskel
+ {
+ author_simpl ();
+
+ virtual void
+ pre (const author&);
+
+ virtual bool
+ recommends_present ();
+
+ virtual std::string
+ recommends ();
+
+ private:
+ person_simpl base_impl_;
+ const author* author_;
+ };
+
+ //
+ //
+ struct book_simpl: book_sskel
+ {
+ virtual void
+ pre (const book&);
+
+ virtual library::isbn
+ isbn ();
+
+ virtual const library::title&
+ title ();
+
+ virtual library::genre
+ genre ();
+
+ virtual bool
+ author_next ();
+
+ virtual const library::author&
+ author ();
+
+ virtual bool
+ available ();
+
+ virtual std::string
+ id ();
+
+ private:
+ const book* book_;
+ book::authors::const_iterator ai_;
+ };
+
+ //
+ //
+ struct catalog_simpl: catalog_sskel
+ {
+ virtual void
+ pre (const catalog&);
+
+ virtual bool
+ book_next ();
+
+ virtual const library::book&
+ book ();
+
+ private:
+ const catalog* catalog_;
+ catalog::const_iterator ci_;
+ };
+}
+
+#endif // LIBRARY_SIMPL_HXX
diff --git a/examples/cxx/serializer/library/library.hxx b/examples/cxx/serializer/library/library.hxx
new file mode 100644
index 0000000..9f8e250
--- /dev/null
+++ b/examples/cxx/serializer/library/library.hxx
@@ -0,0 +1,270 @@
+// file : examples/cxx/serializer/library/library.hxx
+// author : Boris Kolpackov <boris@codesynthesis.com>
+// copyright : not copyrighted - public domain
+
+#ifndef LIBRARY_HXX
+#define LIBRARY_HXX
+
+#include <string>
+#include <vector>
+
+namespace library
+{
+ //
+ //
+ typedef unsigned int isbn;
+
+
+ //
+ //
+ struct title: std::string
+ {
+ title (const std::string& s)
+ : std::string (s)
+ {
+ }
+
+ // lang
+ //
+ const std::string&
+ lang () const
+ {
+ return lang_;
+ }
+
+ void
+ lang (const std::string& lang)
+ {
+ lang_ = lang;
+ }
+
+ private:
+ std::string lang_;
+ };
+
+
+ //
+ //
+ enum genre
+ {
+ romance,
+ fiction,
+ horror,
+ history,
+ philosophy
+ };
+
+
+ //
+ //
+ struct person
+ {
+ person (const std::string& name, const std::string& born)
+ : name_ (name), born_ (born)
+ {
+ }
+
+ // name
+ //
+ const std::string&
+ name () const
+ {
+ return name_;
+ }
+
+ void
+ name (const std::string& name)
+ {
+ name_ = name;
+ }
+
+ // born
+ //
+ const std::string&
+ born () const
+ {
+ return born_;
+ }
+
+ void
+ born (const std::string& born)
+ {
+ born_ = born;
+ }
+
+
+ // died
+ //
+ const std::string&
+ died () const
+ {
+ return died_;
+ }
+
+ void
+ died (const std::string& died)
+ {
+ died_ = died;
+ }
+
+ private:
+ std::string name_;
+ std::string born_;
+ std::string died_;
+ };
+
+
+ //
+ //
+ struct author: person
+ {
+ author (const std::string& name, const std::string& born)
+ : person (name, born)
+ {
+ }
+
+ // recommends
+ //
+ const std::string&
+ recommends () const
+ {
+ return recommends_;
+ }
+
+ void
+ recommends (const std::string& recommends)
+ {
+ recommends_ = recommends;
+ }
+
+ private:
+ std::string recommends_;
+ };
+
+
+ //
+ //
+ struct book
+ {
+ book (library::isbn isbn,
+ const library::title& title,
+ library::genre genre,
+ bool available,
+ const std::string& id)
+ : isbn_ (isbn),
+ title_ (title),
+ genre_ (genre),
+ available_ (available),
+ id_ (id)
+ {
+ }
+
+ // isbn
+ //
+ library::isbn
+ isbn () const
+ {
+ return isbn_;
+ }
+
+ void
+ isbn (const library::isbn& isbn)
+ {
+ isbn_ = isbn;
+ }
+
+
+ // title
+ //
+ const library::title&
+ title () const
+ {
+ return title_;
+ }
+
+ void
+ title (const library::title& title)
+ {
+ title_ = title;
+ }
+
+
+ // genre
+ //
+ library::genre
+ genre () const
+ {
+ return genre_;
+ }
+
+ void
+ genre (const library::genre& genre)
+ {
+ genre_ = genre;
+ }
+
+
+ // author
+ //
+ typedef std::vector<library::author> authors;
+
+ const authors&
+ author () const
+ {
+ return author_;
+ }
+
+ authors&
+ author ()
+ {
+ return author_;
+ }
+
+
+ // available
+ //
+ bool
+ available () const
+ {
+ return available_;
+ }
+
+ void
+ available (bool available)
+ {
+ available_ = available;
+ }
+
+
+ // id
+ //
+ const std::string&
+ id () const
+ {
+ return id_;
+ }
+
+ void
+ id (const std::string& id)
+ {
+ id_ = id;
+ }
+
+ private:
+ library::isbn isbn_;
+ library::title title_;
+ library::genre genre_;
+
+ authors author_;
+
+ bool available_;
+ std::string id_;
+ };
+
+
+ //
+ //
+ typedef std::vector<book> catalog;
+}
+
+#endif // LIBRARY_HXX
diff --git a/examples/cxx/serializer/library/library.map b/examples/cxx/serializer/library/library.map
new file mode 100644
index 0000000..901fb7d
--- /dev/null
+++ b/examples/cxx/serializer/library/library.map
@@ -0,0 +1,22 @@
+# file : examples/cxx/serializer/library/library.map
+# author : Boris Kolpackov <boris@codesynthesis.com>
+# copyright : not copyrighted - public domain
+
+namespace http://www.codesynthesis.com/library
+{
+ include "library.hxx";
+
+ # Use the actual type instead of a typedef. The compiler
+ # has no way of knowing that isbn and unsigned int are
+ # the same C++ types and may generate clashing function
+ # signatures if we use the typedef alias here.
+ #
+ isbn "unsigned int" "unsigned int";
+
+ title "const library::title&";
+ genre library::genre library::genre;
+ person "const library::person&";
+ author "const library::author&";
+ book "const library::book&";
+ catalog "const library::catalog&";
+}
diff --git a/examples/cxx/serializer/library/library.xsd b/examples/cxx/serializer/library/library.xsd
new file mode 100644
index 0000000..05ae2de
--- /dev/null
+++ b/examples/cxx/serializer/library/library.xsd
@@ -0,0 +1,79 @@
+<?xml version="1.0"?>
+
+<!--
+
+file : examples/cxx/serializer/library/library.xsd
+author : Boris Kolpackov <boris@codesynthesis.com>
+copyright : not copyrighted - public domain
+
+-->
+
+<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema"
+ xmlns:lib="http://www.codesynthesis.com/library"
+ targetNamespace="http://www.codesynthesis.com/library">
+
+ <xsd:simpleType name="isbn">
+ <xsd:restriction base="xsd:unsignedInt"/>
+ </xsd:simpleType>
+
+
+ <xsd:complexType name="title">
+ <xsd:simpleContent>
+ <xsd:extension base="xsd:string">
+ <xsd:attribute name="lang" type="xsd:string"/>
+ </xsd:extension>
+ </xsd:simpleContent>
+ </xsd:complexType>
+
+
+ <xsd:simpleType name="genre">
+ <xsd:restriction base="xsd:string">
+ <xsd:enumeration value="romance"/>
+ <xsd:enumeration value="fiction"/>
+ <xsd:enumeration value="horror"/>
+ <xsd:enumeration value="history"/>
+ <xsd:enumeration value="philosophy"/>
+ </xsd:restriction>
+ </xsd:simpleType>
+
+
+ <xsd:complexType name="person">
+ <xsd:sequence>
+ <xsd:element name="name" type="xsd:string"/>
+ <xsd:element name="born" type="xsd:string"/>
+ <xsd:element name="died" type="xsd:string" minOccurs="0"/>
+ </xsd:sequence>
+ </xsd:complexType>
+
+
+ <xsd:complexType name="author">
+ <xsd:complexContent>
+ <xsd:extension base="lib:person">
+ <xsd:attribute name="recommends" type="xsd:IDREF"/> <!-- Book -->
+ </xsd:extension>
+ </xsd:complexContent>
+ </xsd:complexType>
+
+
+ <xsd:complexType name="book">
+ <xsd:sequence>
+ <xsd:element name="isbn" type="lib:isbn"/>
+ <xsd:element name="title" type="lib:title"/>
+ <xsd:element name="genre" type="lib:genre"/>
+ <xsd:element name="author" type="lib:author" maxOccurs="unbounded"/>
+ </xsd:sequence>
+ <xsd:attribute name="available" type="xsd:boolean" use="required"/>
+ <xsd:attribute name="id" type="xsd:ID" use="required"/>
+ </xsd:complexType>
+
+
+ <xsd:complexType name="catalog">
+ <xsd:sequence>
+ <xsd:element name="book" type="lib:book" maxOccurs="unbounded"/>
+ </xsd:sequence>
+ </xsd:complexType>
+
+
+ <xsd:element name="catalog" type="lib:catalog"/>
+
+</xsd:schema>
diff --git a/examples/cxx/serializer/library/makefile b/examples/cxx/serializer/library/makefile
new file mode 100644
index 0000000..ba58e96
--- /dev/null
+++ b/examples/cxx/serializer/library/makefile
@@ -0,0 +1,72 @@
+# file : examples/cxx/serializer/library/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 := library.xsd
+cxx := driver.cxx
+
+ifeq ($(xsde_reuse_style),mixin)
+cxx += library-simpl-mixin.cxx
+else
+cxx += library-simpl-tiein.cxx
+endif
+
+obj := $(addprefix $(out_base)/,$(cxx:.cxx=.o) $(xsd:.xsd=-sskel.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=-sskel.hxx) \
+ $(out_base)/$(xsd:.xsd=-sskel.ixx) \
+ $(out_base)/$(xsd:.xsd=-sskel.cxx)
+
+$(skel): xsde := $(out_root)/xsde/xsde
+$(skel): xsde_options += --generate-inline --type-map $(src_base)/library.map
+
+$(skel): $(out_root)/xsde/xsde $(src_base)/library.map
+
+$(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=-sskel.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/serializer/xsd-cxx.make)
+
+
+# Dependencies.
+#
+$(call import,$(src_root)/xsde/makefile)
+$(call import,$(src_root)/libxsde/xsde/makefile)
diff --git a/examples/cxx/serializer/makefile b/examples/cxx/serializer/makefile
new file mode 100644
index 0000000..0bda4e8
--- /dev/null
+++ b/examples/cxx/serializer/makefile
@@ -0,0 +1,49 @@
+# file : examples/cxx/serializer/makefile
+# author : Boris Kolpackov <boris@codesynthesis.com>
+# copyright : Copyright (c) 2006-2009 Code Synthesis Tools CC
+# license : GNU GPL v2 + exceptions; see accompanying LICENSE file
+
+include $(dir $(lastword $(MAKEFILE_LIST)))../../../build/bootstrap.make
+
+examples :=
+
+ifeq ($(xsde_stl),y)
+ifeq ($(xsde_iostream),y)
+ifeq ($(xsde_exceptions),y)
+
+examples += hello
+
+ifneq ($(xsde_reuse_style),none)
+examples += library
+
+ifeq ($(xsde_polymorphic),y)
+examples += polymorphism polyroot
+endif
+
+endif
+
+ifeq ($(xsde_reuse_style),tiein)
+examples += wildcard
+endif
+
+endif
+endif
+endif
+
+ifeq ($(xsde_stl),n)
+ifeq ($(xsde_exceptions),n)
+ifneq ($(xsde_reuse_style),none)
+examples += minimal
+endif
+endif
+endif
+
+default := $(out_base)/
+clean := $(out_base)/.clean
+
+.PHONY: $(default) $(clean)
+
+$(default): $(addprefix $(out_base)/,$(addsuffix /,$(examples)))
+$(clean): $(addprefix $(out_base)/,$(addsuffix /.clean,$(examples)))
+
+$(foreach e,$(examples),$(call import,$(src_base)/$e/makefile))
diff --git a/examples/cxx/serializer/minimal/README b/examples/cxx/serializer/minimal/README
new file mode 100644
index 0000000..0121f9a
--- /dev/null
+++ b/examples/cxx/serializer/minimal/README
@@ -0,0 +1,47 @@
+This example is a minimal serializer implementation that is
+intended to work without STL, iostream, or C++ exceptions.
+
+The example consists of the following files:
+
+people.xsd
+ XML Schema which describes a collection of person
+ records.
+
+people.hxx
+ Simple C++ types that corresponds to the XML Schema
+ types in people.xsd. These are hand-written.
+
+people.map
+ Type map. It maps XML Schema types defined in
+ people.xsd to C++ types defined in people.hxx.
+
+people-sskel.hxx
+people-sskel.ixx
+people-sskel.cxx
+ Serializer skeletons generated by XSD/e from people.xsd
+ and people.map. The --no-stl and --no-iostream options
+ were used to produce these files.
+
+people-simpl-mixin.hxx
+
+people-simpl-tiein.hxx
+ Serializer implementations (using either mixin or tiein
+ parser reuse style) that serializes the custom in-memory
+ object model defined in people.hxx to XML. These are hand-
+ written implementations of the parser skeletons defined
+ in people-sskel.hxx.
+
+driver.cxx
+ Driver for the example. It first constructs a sample
+ object model using the types from people.hxx. It then
+ creates a serializer instance using the serializer
+ implementation mentioned above and a couple of predefined
+ serializers for the XML Schema built-in types. Finally, it
+ invokes this serializer instance to serialize the sample
+ object model to an XML document which is printed to STDOUT.
+ It also shows how to handle serialization and validation
+ errors using error codes.
+
+To run the example simply execute:
+
+$ ./driver
diff --git a/examples/cxx/serializer/minimal/driver.cxx b/examples/cxx/serializer/minimal/driver.cxx
new file mode 100644
index 0000000..df8d7f0
--- /dev/null
+++ b/examples/cxx/serializer/minimal/driver.cxx
@@ -0,0 +1,139 @@
+// file : examples/cxx/serializer/minimal/driver.cxx
+// author : Boris Kolpackov <boris@codesynthesis.com>
+// copyright : not copyrighted - public domain
+
+#include <stdio.h>
+
+#include "people.hxx"
+#include "people-sskel.hxx" // Get the configuration macros (XSDE_*).
+
+#if defined(XSDE_REUSE_STYLE_MIXIN)
+# include "people-simpl-mixin.hxx"
+#elif defined(XSDE_REUSE_STYLE_TIEIN)
+# include "people-simpl-tiein.hxx"
+#else
+# error this example requires mixin or tiein serializer reuse support
+#endif
+
+struct writer: xml_schema::writer
+{
+ virtual bool
+ write (const char* s, size_t n)
+ {
+ return fwrite (s, n, 1, stdout) == 1;
+ }
+
+ virtual bool
+ flush ()
+ {
+ return fflush (stdout) == 0;
+ }
+};
+
+int
+main ()
+{
+ // Create a sample person list.
+ //
+ people p;
+
+ p.size_ = 2;
+ p.people_ = new person[p.size_];
+
+ if (p.people_ == 0)
+ {
+ fprintf (stderr, "error: no memory\n");
+ return 1;
+ }
+
+ p.people_[0].first_name_ = "John";
+ p.people_[0].last_name_ = "Doe";
+ p.people_[0].gender_ = male;
+ p.people_[0].age_ = 32;
+
+ p.people_[1].first_name_ = "Jane";
+ p.people_[1].last_name_ = "Doe";
+ p.people_[1].gender_ = female;
+ p.people_[1].age_ = 28;
+
+ // Construct the serializer.
+ //
+ xml_schema::unsigned_short_simpl unsigned_short_s;
+ xml_schema::string_simpl string_s;
+
+ gender_simpl gender_s;
+ person_simpl person_s;
+ people_simpl people_s;
+
+ person_s.serializers (string_s, string_s, gender_s, unsigned_short_s);
+ people_s.serializers (person_s);
+
+ // Serialize.
+ //
+ typedef xml_schema::serializer_error error;
+
+ error e;
+ writer w;
+
+ do
+ {
+ xml_schema::document_simpl doc_s (people_s, "people");
+
+ if (e = doc_s._error ())
+ break;
+
+ people_s.pre (p);
+
+ if (e = people_s._error ())
+ break;
+
+ doc_s.serialize (w);
+
+ if (e = doc_s._error ())
+ break;
+
+ people_s.post ();
+
+ e = people_s._error ();
+
+ } while (false);
+
+ delete[] p.people_;
+
+ // Handle errors.
+ //
+ if (e)
+ {
+ switch (e.type ())
+ {
+ case error::sys:
+ {
+ fprintf (stderr, "error: %s\n", e.sys_text ());
+ break;
+ }
+ case error::xml:
+ {
+ fprintf (stderr, "error: %s\n", e.xml_text ());
+ break;
+ }
+#ifdef XSDE_SERIALIZER_VALIDATION
+ case error::schema:
+ {
+ fprintf (stderr, "error: %s\n", e.schema_text ());
+ break;
+ }
+#endif
+ case error::app:
+ {
+ fprintf (stderr, "application error: %d\n", e.app_code ());
+ break;
+ }
+ default:
+ break;
+ }
+
+ return 1;
+ }
+
+ return 0;
+}
diff --git a/examples/cxx/serializer/minimal/makefile b/examples/cxx/serializer/minimal/makefile
new file mode 100644
index 0000000..3337728
--- /dev/null
+++ b/examples/cxx/serializer/minimal/makefile
@@ -0,0 +1,66 @@
+# file : examples/cxx/serializer/minimal/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 := people.xsd
+cxx := driver.cxx
+
+obj := $(addprefix $(out_base)/,$(cxx:.cxx=.o) $(xsd:.xsd=-sskel.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=-sskel.hxx) \
+ $(out_base)/$(xsd:.xsd=-sskel.ixx) \
+ $(out_base)/$(xsd:.xsd=-sskel.cxx)
+
+$(skel): xsde := $(out_root)/xsde/xsde
+$(skel): xsde_options += --type-map $(src_base)/people.map
+
+$(skel): $(out_root)/xsde/xsde $(src_base)/people.map
+
+$(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=-sskel.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/serializer/xsd-cxx.make)
+
+
+# Dependencies.
+#
+$(call import,$(src_root)/xsde/makefile)
+$(call import,$(src_root)/libxsde/xsde/makefile)
diff --git a/examples/cxx/serializer/minimal/people-simpl-mixin.hxx b/examples/cxx/serializer/minimal/people-simpl-mixin.hxx
new file mode 100644
index 0000000..635bed2
--- /dev/null
+++ b/examples/cxx/serializer/minimal/people-simpl-mixin.hxx
@@ -0,0 +1,82 @@
+// file : examples/cxx/serializer/people/people-simpl-mixin.hxx
+// author : Boris Kolpackov <boris@codesynthesis.com>
+// copyright : not copyrighted - public domain
+
+#ifndef PEOPLE_SIMPL_HXX
+#define PEOPLE_SIMPL_HXX
+
+#include "people.hxx"
+#include "people-sskel.hxx"
+
+struct gender_simpl: virtual gender_sskel, xml_schema::string_simpl
+{
+ virtual void
+ pre (gender g)
+ {
+ string_simpl::pre (g == male ? "male" : "female");
+ }
+};
+
+struct person_simpl: virtual person_sskel
+{
+ virtual void
+ pre (const person& p)
+ {
+ person_ = &p;
+ }
+
+ virtual const char*
+ first_name ()
+ {
+ return person_->first_name_;
+ }
+
+ virtual const char*
+ last_name ()
+ {
+ return person_->last_name_;
+ }
+
+ virtual ::gender
+ gender ()
+ {
+ return person_->gender_;
+ }
+
+ virtual unsigned short
+ age ()
+ {
+ return person_->age_;
+ }
+
+private:
+ const person* person_;
+};
+
+struct people_simpl: virtual people_sskel
+{
+ virtual void
+ pre (const people& p)
+ {
+ i_ = 0;
+ people_ = &p;
+ }
+
+ virtual bool
+ person_next ()
+ {
+ return i_ < people_->size_;
+ }
+
+ virtual const ::person&
+ person ()
+ {
+ return people_->people_[i_++];
+ }
+
+private:
+ size_t i_;
+ const people* people_;
+};
+
+#endif // PEOPLE_SIMPL_HXX
diff --git a/examples/cxx/serializer/minimal/people-simpl-tiein.hxx b/examples/cxx/serializer/minimal/people-simpl-tiein.hxx
new file mode 100644
index 0000000..ce7a70d
--- /dev/null
+++ b/examples/cxx/serializer/minimal/people-simpl-tiein.hxx
@@ -0,0 +1,90 @@
+// file : examples/cxx/serializer/people/people-simpl-tiein.hxx
+// author : Boris Kolpackov <boris@codesynthesis.com>
+// copyright : not copyrighted - public domain
+
+#ifndef PEOPLE_SIMPL_HXX
+#define PEOPLE_SIMPL_HXX
+
+#include "people.hxx"
+#include "people-sskel.hxx"
+
+struct gender_simpl: gender_sskel
+{
+ gender_simpl ()
+ : gender_sskel (&base_impl_)
+ {
+ }
+
+ virtual void
+ pre (gender g)
+ {
+ base_impl_.pre (g == male ? "male" : "female");
+ }
+
+private:
+ xml_schema::string_simpl base_impl_;
+};
+
+struct person_simpl: person_sskel
+{
+ virtual void
+ pre (const person& p)
+ {
+ person_ = &p;
+ }
+
+ virtual const char*
+ first_name ()
+ {
+ return person_->first_name_;
+ }
+
+ virtual const char*
+ last_name ()
+ {
+ return person_->last_name_;
+ }
+
+ virtual ::gender
+ gender ()
+ {
+ return person_->gender_;
+ }
+
+ virtual unsigned short
+ age ()
+ {
+ return person_->age_;
+ }
+
+private:
+ const person* person_;
+};
+
+struct people_simpl: people_sskel
+{
+ virtual void
+ pre (const people& p)
+ {
+ i_ = 0;
+ people_ = &p;
+ }
+
+ virtual bool
+ person_next ()
+ {
+ return i_ < people_->size_;
+ }
+
+ virtual const ::person&
+ person ()
+ {
+ return people_->people_[i_++];
+ }
+
+private:
+ size_t i_;
+ const people* people_;
+};
+
+#endif // PEOPLE_SIMPL_HXX
diff --git a/examples/cxx/serializer/minimal/people.hxx b/examples/cxx/serializer/minimal/people.hxx
new file mode 100644
index 0000000..94ae37d
--- /dev/null
+++ b/examples/cxx/serializer/minimal/people.hxx
@@ -0,0 +1,30 @@
+// file : examples/cxx/serializer/minimal/people.hxx
+// author : Boris Kolpackov <boris@codesynthesis.com>
+// copyright : not copyrighted - public domain
+
+#ifndef PEOPLE_HXX
+#define PEOPLE_HXX
+
+#include <stddef.h> // size_t
+
+enum gender
+{
+ male,
+ female
+};
+
+struct person
+{
+ const char* first_name_;
+ const char* last_name_;
+ gender gender_;
+ unsigned short age_;
+};
+
+struct people
+{
+ person* people_;
+ size_t size_;
+};
+
+#endif // PEOPLE_HXX
diff --git a/examples/cxx/serializer/minimal/people.map b/examples/cxx/serializer/minimal/people.map
new file mode 100644
index 0000000..6f51d5b
--- /dev/null
+++ b/examples/cxx/serializer/minimal/people.map
@@ -0,0 +1,9 @@
+# file : examples/cxx/serializer/minimal/people.map
+# author : Boris Kolpackov <boris@codesynthesis.com>
+# copyright : not copyrighted - public domain
+
+include "people.hxx";
+
+gender ::gender ::gender;
+person "const ::person&";
+people "const ::people&";
diff --git a/examples/cxx/serializer/minimal/people.xsd b/examples/cxx/serializer/minimal/people.xsd
new file mode 100644
index 0000000..d5e4e1f
--- /dev/null
+++ b/examples/cxx/serializer/minimal/people.xsd
@@ -0,0 +1,37 @@
+<?xml version="1.0"?>
+
+<!--
+
+file : examples/cxx/serializer/minimal/people.xsd
+author : Boris Kolpackov <boris@codesynthesis.com>
+copyright : not copyrighted - public domain
+
+-->
+
+<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema">
+
+ <xsd:simpleType name="gender">
+ <xsd:restriction base="xsd:string">
+ <xsd:enumeration value="male"/>
+ <xsd:enumeration value="female"/>
+ </xsd:restriction>
+ </xsd:simpleType>
+
+ <xsd:complexType name="person">
+ <xsd:sequence>
+ <xsd:element name="first-name" type="xsd:string"/>
+ <xsd:element name="last-name" type="xsd:string"/>
+ <xsd:element name="gender" type="gender"/>
+ <xsd:element name="age" type="xsd:unsignedShort"/>
+ </xsd:sequence>
+ </xsd:complexType>
+
+ <xsd:complexType name="people">
+ <xsd:sequence>
+ <xsd:element name="person" type="person" maxOccurs="unbounded"/>
+ </xsd:sequence>
+ </xsd:complexType>
+
+ <xsd:element name="people" type="people"/>
+
+</xsd:schema>
diff --git a/examples/cxx/serializer/polymorphism/README b/examples/cxx/serializer/polymorphism/README
new file mode 100644
index 0000000..0e2c5b8
--- /dev/null
+++ b/examples/cxx/serializer/polymorphism/README
@@ -0,0 +1,44 @@
+This example shows how to handle XML Schema polymorphism features such as
+xsi:type attributes and substitution groups in the Embedded C++/Serializer
+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.hxx
+ Types that describe the supermen object model in C++. These
+ are hand-written.
+
+supermen.map
+ Type map. It maps XML Schema types defined in supermen.xsd to
+ C++ types defined in supermen.hxx.
+
+supermen-sskel.hxx
+supermen-sskel.cxx
+ Serializer skeletons generated by XSD/e from supermen.xsd and
+ supermen.map.
+
+supermen-simpl-mixin.hxx
+supermen-simpl-mixin.cxx
+
+supermen-simpl-tiein.hxx
+supermen-simpl-tiein.cxx
+ Serializer implementations (using either mixin or tiein parser
+ reuse style) that serialize the custom in-memory object model to
+ XML. These are hand-written implementations of the serializer
+ skeletons defined in supermen-sskel.hxx.
+
+driver.cxx
+ Driver for the example. It first constructs a sample object model
+ using the types from supermen.hxx. It then creates a serializer
+ instance using all the individual serializers found in one of
+ supermen-simpl-*.hxx. Finally, it invokes this serializer instance
+ to serialize the sample object model to an XML document which is
+ printed to STDOUT.
+
+To run the example simply execute:
+
+$ ./driver
diff --git a/examples/cxx/serializer/polymorphism/driver.cxx b/examples/cxx/serializer/polymorphism/driver.cxx
new file mode 100644
index 0000000..3015133
--- /dev/null
+++ b/examples/cxx/serializer/polymorphism/driver.cxx
@@ -0,0 +1,120 @@
+// file : examples/cxx/serializer/polymorphism/driver.cxx
+// author : Boris Kolpackov <boris@codesynthesis.com>
+// copyright : not copyrighted - public domain
+
+#include <iostream>
+
+#include "supermen.hxx"
+
+#include "supermen-sskel.hxx" // Get the configuration macros (XSDE_*).
+
+#if defined(XSDE_REUSE_STYLE_MIXIN)
+# include "supermen-simpl-mixin.hxx"
+#elif defined(XSDE_REUSE_STYLE_TIEIN)
+# include "supermen-simpl-tiein.hxx"
+#else
+# error this example requires mixin or tiein serializer reuse support
+#endif
+
+using std::cerr;
+using std::endl;
+
+int
+main ()
+{
+ // Check that the load in substitution and inheritance hashmaps
+ // is not too high.
+ //
+#ifndef NDEBUG
+ float load = (float) xml_schema::serializer_smap_elements ();
+ load /= xml_schema::serializer_smap_buckets ();
+
+ if (load > 0.8)
+ {
+ cerr << "substitution hashmap load is " << load << endl;
+ cerr << "time to increase XSDE_SERIALIZER_SMAP_BUCKETS" << endl;
+ }
+
+ load = (float) xml_schema::serializer_smap_bucket_elements ();
+ load /= xml_schema::serializer_smap_bucket_buckets ();
+
+ if (load > 0.8)
+ {
+ cerr << "substitution inner hashmap load is " << load << endl;
+ cerr << "time to increase XSDE_SERIALIZER_SMAP_BUCKET_BUCKETS" << endl;
+ }
+
+#ifdef XSDE_SERIALIZER_VALIDATION
+ load = (float) xml_schema::serializer_imap_elements ();
+ load /= xml_schema::serializer_imap_buckets ();
+
+ if (load > 0.8)
+ {
+ cerr << "inheritance hashmap load is " << load << endl;
+ cerr << "time to increase XSDE_SERIALIZER_IMAP_BUCKETS" << endl;
+ }
+#endif
+#endif
+
+ try
+ {
+ // Create a sample supermen catalog. To keep things simple the
+ // following code is not exception-safe.
+ //
+ supermen sm;
+
+ sm.push_back (new person ("John Doe"));
+ sm.push_back (new superman ("James 007 Bond", false));
+ sm.push_back (new batman ("Bruce Wayne", 10));
+
+ // Construct the serializer.
+ //
+ xml_schema::string_simpl string_s;
+ xml_schema::boolean_simpl boolean_s;
+ xml_schema::unsigned_int_simpl unsigned_int_s;
+
+ person_simpl person_s;
+ superman_simpl superman_s;
+ batman_simpl batman_s;
+
+ xml_schema::serializer_map_impl person_map (5); // 5 hashtable buckets
+ supermen_simpl supermen_s;
+
+ person_s.serializers (string_s);
+ superman_s.serializers (string_s, boolean_s);
+ batman_s.serializers (string_s, boolean_s, unsigned_int_s);
+
+ // Here we are specifying several serializers that can be
+ // used to serialize the person element.
+ //
+ person_map.insert (person_s);
+ person_map.insert (superman_s);
+ person_map.insert (batman_s);
+
+ supermen_s.person_serializer (person_map);
+
+ // Create the XML instance document. The last argument to the
+ // document's constructor indicates that we are serializing
+ // polymorphic XML documents.
+ //
+ xml_schema::document_simpl doc_s (supermen_s, "supermen", true);
+
+ doc_s.add_no_namespace_schema ("supermen.xsd");
+
+ supermen_s.pre (sm);
+ doc_s.serialize (std::cout);
+ supermen_s.post ();
+ }
+ catch (const xml_schema::serializer_exception& e)
+ {
+ cerr << "error: " << e.text () << endl;
+ return 1;
+ }
+ catch (const std::ios_base::failure&)
+ {
+ cerr << "error: write failure" << endl;
+ return 1;
+ }
+
+ return 0;
+}
diff --git a/examples/cxx/serializer/polymorphism/makefile b/examples/cxx/serializer/polymorphism/makefile
new file mode 100644
index 0000000..1841794
--- /dev/null
+++ b/examples/cxx/serializer/polymorphism/makefile
@@ -0,0 +1,73 @@
+# file : examples/cxx/serializer/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-simpl-mixin.cxx
+else
+cxx += supermen-simpl-tiein.cxx
+endif
+
+obj := $(addprefix $(out_base)/,$(cxx:.cxx=.o) $(xsd:.xsd=-sskel.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=-sskel.hxx) \
+ $(out_base)/$(xsd:.xsd=-sskel.ixx) \
+ $(out_base)/$(xsd:.xsd=-sskel.cxx)
+
+$(skel): xsde := $(out_root)/xsde/xsde
+$(skel): xsde_options += --generate-polymorphic \
+--type-map $(src_base)/supermen.map
+
+$(skel): $(out_root)/xsde/xsde $(src_base)/supermen.map
+
+$(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=-sskel.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/serializer/xsd-cxx.make)
+
+
+# Dependencies.
+#
+$(call import,$(src_root)/xsde/makefile)
+$(call import,$(src_root)/libxsde/xsde/makefile)
diff --git a/examples/cxx/serializer/polymorphism/supermen-simpl-mixin.cxx b/examples/cxx/serializer/polymorphism/supermen-simpl-mixin.cxx
new file mode 100644
index 0000000..328cc2f
--- /dev/null
+++ b/examples/cxx/serializer/polymorphism/supermen-simpl-mixin.cxx
@@ -0,0 +1,83 @@
+// file : examples/cxx/serializer/polymorphism/supermen-simpl-mixin.cxx
+// author : Boris Kolpackov <boris@codesynthesis.com>
+// copyright : not copyrighted - public domain
+
+#include "supermen-simpl-mixin.hxx"
+
+//
+//
+void person_simpl::
+pre (const person& p)
+{
+ person_ = &p;
+}
+
+std::string person_simpl::
+name ()
+{
+ return person_->name ();
+}
+
+//
+//
+bool superman_simpl::
+can_fly ()
+{
+ return static_cast<const superman*> (person_)->can_fly ();
+}
+
+//
+//
+unsigned int batman_simpl::
+wing_span ()
+{
+ return static_cast<const batman*> (person_)->wing_span ();
+}
+
+//
+//
+void supermen_simpl::
+pre (const supermen& s)
+{
+ supermen_ = &s;
+ i_ = s.begin ();
+}
+
+bool supermen_simpl::
+person_next ()
+{
+ return i_ != supermen_->end ();
+}
+
+const person& supermen_simpl::
+person ()
+{
+ const ::person& p = **i_++;
+
+ // Map type id to serializer type. We could have also done this in a
+ // custom serializer_map implementation in which case we could simply
+ // pass a pointer to the person instance as type id.
+ //
+ xml_schema::serializer_context& ctx = _context ();
+
+ switch (p.type ())
+ {
+ case person_type:
+ {
+ ctx.type_id (person_sskel::_static_type ());
+ break;
+ }
+ case superman_type:
+ {
+ ctx.type_id (superman_sskel::_static_type ());
+ break;
+ }
+ case batman_type:
+ {
+ ctx.type_id (batman_sskel::_static_type ());
+ break;
+ }
+ }
+
+ return p;
+}
diff --git a/examples/cxx/serializer/polymorphism/supermen-simpl-mixin.hxx b/examples/cxx/serializer/polymorphism/supermen-simpl-mixin.hxx
new file mode 100644
index 0000000..04b8b18
--- /dev/null
+++ b/examples/cxx/serializer/polymorphism/supermen-simpl-mixin.hxx
@@ -0,0 +1,51 @@
+// file : examples/cxx/serializer/polymorphism/library-simpl-mixin.hxx
+// author : Boris Kolpackov <boris@codesynthesis.com>
+// copyright : not copyrighted - public domain
+
+#ifndef SUPERMEN_SIMPL_HXX
+#define SUPERMEN_SIMPL_HXX
+
+#include "supermen.hxx"
+#include "supermen-sskel.hxx"
+
+struct person_simpl: virtual person_sskel
+{
+ virtual void
+ pre (const person&);
+
+ virtual std::string
+ name ();
+
+protected:
+ const person* person_;
+};
+
+struct superman_simpl: virtual superman_sskel, person_simpl
+{
+ virtual bool
+ can_fly ();
+};
+
+struct batman_simpl: virtual batman_sskel, superman_simpl
+{
+ virtual unsigned int
+ wing_span ();
+};
+
+struct supermen_simpl: virtual supermen_sskel
+{
+ virtual void
+ pre (const supermen&);
+
+ virtual bool
+ person_next ();
+
+ virtual const ::person&
+ person ();
+
+private:
+ const supermen* supermen_;
+ supermen::const_iterator i_;
+};
+
+#endif // SUPERMEN_SIMPL_HXX
diff --git a/examples/cxx/serializer/polymorphism/supermen-simpl-tiein.cxx b/examples/cxx/serializer/polymorphism/supermen-simpl-tiein.cxx
new file mode 100644
index 0000000..77466b3
--- /dev/null
+++ b/examples/cxx/serializer/polymorphism/supermen-simpl-tiein.cxx
@@ -0,0 +1,108 @@
+// file : examples/cxx/serializer/polymorphism/supermen-simpl-tiein.cxx
+// author : Boris Kolpackov <boris@codesynthesis.com>
+// copyright : not copyrighted - public domain
+
+#include "supermen-simpl-tiein.hxx"
+
+//
+//
+void person_simpl::
+pre (const person& p)
+{
+ person_ = &p;
+}
+
+std::string person_simpl::
+name ()
+{
+ return person_->name ();
+}
+
+//
+//
+superman_simpl::
+superman_simpl ()
+ : superman_sskel (&base_impl_)
+{
+}
+
+bool superman_simpl::
+can_fly ()
+{
+ return superman_ ().can_fly ();
+}
+
+const superman& superman_simpl::
+superman_ ()
+{
+ return *static_cast<const superman*> (base_impl_.person_);
+}
+
+//
+//
+batman_simpl::
+batman_simpl ()
+ : batman_sskel (&base_impl_)
+{
+}
+
+unsigned int batman_simpl::
+wing_span ()
+{
+ return batman_ ().wing_span ();
+}
+
+const batman& batman_simpl::
+batman_ ()
+{
+ return static_cast<const batman&> (base_impl_.superman_ ());
+}
+
+//
+//
+void supermen_simpl::
+pre (const supermen& s)
+{
+ supermen_ = &s;
+ i_ = s.begin ();
+}
+
+bool supermen_simpl::
+person_next ()
+{
+ return i_ != supermen_->end ();
+}
+
+const person& supermen_simpl::
+person ()
+{
+ const ::person& p = **i_++;
+
+ // Map type id to serializer type. We could have also done this in a
+ // custom serializer_map implementation in which case we could simply
+ // pass a pointer to the person instance as type id.
+ //
+ xml_schema::serializer_context& ctx = _context ();
+
+ switch (p.type ())
+ {
+ case person_type:
+ {
+ ctx.type_id (person_sskel::_static_type ());
+ break;
+ }
+ case superman_type:
+ {
+ ctx.type_id (superman_sskel::_static_type ());
+ break;
+ }
+ case batman_type:
+ {
+ ctx.type_id (batman_sskel::_static_type ());
+ break;
+ }
+ }
+
+ return p;
+}
+
diff --git a/examples/cxx/serializer/polymorphism/supermen-simpl-tiein.hxx b/examples/cxx/serializer/polymorphism/supermen-simpl-tiein.hxx
new file mode 100644
index 0000000..806d017
--- /dev/null
+++ b/examples/cxx/serializer/polymorphism/supermen-simpl-tiein.hxx
@@ -0,0 +1,69 @@
+// file : examples/cxx/serializer/polymorphism/supermen-simpl-tiein.hxx
+// author : Boris Kolpackov <boris@codesynthesis.com>
+// copyright : not copyrighted - public domain
+
+#ifndef SUPERMEN_SIMPL_HXX
+#define SUPERMEN_SIMPL_HXX
+
+#include "supermen.hxx"
+#include "supermen-sskel.hxx"
+
+struct person_simpl: person_sskel
+{
+ virtual void
+ pre (const person&);
+
+ virtual std::string
+ name ();
+
+ // Derived serializers need access to this variable.
+ //
+public:
+ const person* person_;
+};
+
+struct superman_simpl: superman_sskel
+{
+ superman_simpl ();
+
+ virtual bool
+ can_fly ();
+
+ const superman&
+ superman_ ();
+
+private:
+ person_simpl base_impl_;
+};
+
+struct batman_simpl: batman_sskel
+{
+ batman_simpl ();
+
+ virtual unsigned int
+ wing_span ();
+
+ const batman&
+ batman_ ();
+
+private:
+ superman_simpl base_impl_;
+};
+
+struct supermen_simpl: supermen_sskel
+{
+ virtual void
+ pre (const supermen&);
+
+ virtual bool
+ person_next ();
+
+ virtual const ::person&
+ person ();
+
+private:
+ const supermen* supermen_;
+ supermen::const_iterator i_;
+};
+
+#endif // SUPERMEN_SIMPL_HXX
diff --git a/examples/cxx/serializer/polymorphism/supermen.hxx b/examples/cxx/serializer/polymorphism/supermen.hxx
new file mode 100644
index 0000000..a04b8dd
--- /dev/null
+++ b/examples/cxx/serializer/polymorphism/supermen.hxx
@@ -0,0 +1,129 @@
+// file : examples/cxx/serializer/polymorphism/supermen.hxx
+// author : Boris Kolpackov <boris@codesynthesis.com>
+// copyright : not copyrighted - public domain
+
+#ifndef SUPERMEN_HXX
+#define SUPERMEN_HXX
+
+#include <string>
+#include <vector>
+
+// Custom type id. We could also use standard C++ typeid/type_info
+// if it is available.
+//
+enum type_id
+{
+ person_type,
+ superman_type,
+ batman_type
+};
+
+//
+//
+struct person
+{
+ virtual
+ ~person ()
+ {
+ }
+
+ person (const std::string& name)
+ : name_ (name)
+ {
+ }
+
+ const std::string&
+ name () const
+ {
+ return name_;
+ }
+
+ void
+ name (const std::string& n)
+ {
+ name_ = n;
+ }
+
+ virtual type_id
+ type () const
+ {
+ return person_type;
+ }
+
+private:
+ std::string name_;
+};
+
+//
+//
+struct superman: person
+{
+ superman (const std::string& name, bool can_fly)
+ : person (name), can_fly_ (can_fly)
+ {
+ }
+
+ bool
+ can_fly () const
+ {
+ return can_fly_;
+ }
+
+ void
+ can_fly (bool cf)
+ {
+ can_fly_ = cf;
+ }
+
+ virtual type_id
+ type () const
+ {
+ return superman_type;
+ }
+
+private:
+ bool can_fly_;
+};
+
+struct batman: superman
+{
+ batman (const std::string& name, unsigned int wing_span)
+ : superman (name, true), wing_span_ (wing_span)
+ {
+ }
+
+ unsigned int
+ wing_span () const
+ {
+ return wing_span_;
+ }
+
+ void
+ wing_span (unsigned int ws)
+ {
+ wing_span_ = ws;
+ }
+
+ virtual type_id
+ type () const
+ {
+ return batman_type;
+ }
+
+private:
+ unsigned int wing_span_;
+};
+
+// Poor man's polymorphic sequence which also assumes ownership of the
+// elements.
+//
+struct supermen: std::vector<person*>
+{
+ ~supermen ()
+ {
+ for (iterator i = begin (); i != end (); ++i)
+ delete *i;
+ }
+};
+
+#endif // SUPERMEN_HXX
diff --git a/examples/cxx/serializer/polymorphism/supermen.map b/examples/cxx/serializer/polymorphism/supermen.map
new file mode 100644
index 0000000..ef39a19
--- /dev/null
+++ b/examples/cxx/serializer/polymorphism/supermen.map
@@ -0,0 +1,10 @@
+# file : examples/cxx/serializer/polymorphism/supermen.map
+# author : Boris Kolpackov <boris@codesynthesis.com>
+# copyright : not copyrighted - public domain
+
+include "supermen.hxx";
+
+person "const ::person&";
+superman "const ::person&";
+batman "const ::person&";
+supermen "const ::supermen&";
diff --git a/examples/cxx/serializer/polymorphism/supermen.xsd b/examples/cxx/serializer/polymorphism/supermen.xsd
new file mode 100644
index 0000000..890c7e4
--- /dev/null
+++ b/examples/cxx/serializer/polymorphism/supermen.xsd
@@ -0,0 +1,49 @@
+<?xml version="1.0"?>
+
+<!--
+
+file : examples/cxx/serializer/polymorphism/schema.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>
diff --git a/examples/cxx/serializer/polyroot/README b/examples/cxx/serializer/polyroot/README
new file mode 100644
index 0000000..bd86188
--- /dev/null
+++ b/examples/cxx/serializer/polyroot/README
@@ -0,0 +1,46 @@
+This example shows how to handle the xsi:type attributes and substitution
+groups when they are used on root elements. For general coverage of XML
+Schema polymorphism handling in the Embedded C++/Serializer mapping see
+the polymorphism example.
+
+The example consists of the following files:
+
+supermen.xsd
+ XML Schema which describes supermen instance documents.
+
+supermen.hxx
+ Types that describe the supermen object model in C++. These
+ are hand-written.
+
+supermen.map
+ Type map. It maps XML Schema types defined in supermen.xsd to
+ C++ types defined in supermen.hxx.
+
+supermen-sskel.hxx
+supermen-sskel.cxx
+ Serializer skeletons generated by XSD/e from supermen.xsd and
+ supermen.map.
+
+supermen-simpl-mixin.hxx
+supermen-simpl-mixin.cxx
+
+supermen-simpl-tiein.hxx
+supermen-simpl-tiein.cxx
+ Serializer implementations (using either mixin or tiein parser
+ reuse style) that serialize the custom in-memory object model to
+ XML. These are hand-written implementations of the serializer
+ skeletons defined in supermen-sskel.hxx.
+
+driver.cxx
+ Driver for the example. It first constructs a sample object model
+ using the types from supermen.hxx. It then creates a serializer
+ instance using all the individual serializers found in one of
+ supermen-simpl-*.hxx. Finally, it iterates over the object model
+ and based on the type of the item being serialized, it creates
+ the corresponding document serializer that is then invoked to
+ serialize the object model item to an XML document which is
+ printed to STDOUT.
+
+To run the example simply execute:
+
+$ ./driver
diff --git a/examples/cxx/serializer/polyroot/driver.cxx b/examples/cxx/serializer/polyroot/driver.cxx
new file mode 100644
index 0000000..d404d15
--- /dev/null
+++ b/examples/cxx/serializer/polyroot/driver.cxx
@@ -0,0 +1,142 @@
+// file : examples/cxx/serializer/polyroot/driver.cxx
+// author : Boris Kolpackov <boris@codesynthesis.com>
+// copyright : not copyrighted - public domain
+
+#include <iostream>
+
+#include "supermen.hxx"
+
+#include "supermen-sskel.hxx" // Get the configuration macros (XSDE_*).
+
+#if defined(XSDE_REUSE_STYLE_MIXIN)
+# include "supermen-simpl-mixin.hxx"
+#elif defined(XSDE_REUSE_STYLE_TIEIN)
+# include "supermen-simpl-tiein.hxx"
+#else
+# error this example requires mixin or tiein serializer reuse support
+#endif
+
+using std::cerr;
+using std::endl;
+
+int
+main ()
+{
+ // Check that the load in substitution and inheritance hashmaps
+ // is not too high.
+ //
+#ifndef NDEBUG
+ float load = (float) xml_schema::serializer_smap_elements ();
+ load /= xml_schema::serializer_smap_buckets ();
+
+ if (load > 0.8)
+ {
+ cerr << "substitution hashmap load is " << load << endl;
+ cerr << "time to increase XSDE_SERIALIZER_SMAP_BUCKETS" << endl;
+ }
+
+ load = (float) xml_schema::serializer_smap_bucket_elements ();
+ load /= xml_schema::serializer_smap_bucket_buckets ();
+
+ if (load > 0.8)
+ {
+ cerr << "substitution inner hashmap load is " << load << endl;
+ cerr << "time to increase XSDE_SERIALIZER_SMAP_BUCKET_BUCKETS" << endl;
+ }
+
+#ifdef XSDE_SERIALIZER_VALIDATION
+ load = (float) xml_schema::serializer_imap_elements ();
+ load /= xml_schema::serializer_imap_buckets ();
+
+ if (load > 0.8)
+ {
+ cerr << "inheritance hashmap load is " << load << endl;
+ cerr << "time to increase XSDE_SERIALIZER_IMAP_BUCKETS" << endl;
+ }
+#endif
+#endif
+
+ try
+ {
+ // Create a sample supermen catalog. To keep things simple the
+ // following code is not exception-safe.
+ //
+ supermen sm;
+
+ sm.push_back (new person ("John Doe"));
+ sm.push_back (new superman ("James 007 Bond", false));
+ sm.push_back (new batman ("Bruce Wayne", 10));
+
+ // Construct the serializer.
+ //
+ xml_schema::string_simpl string_s;
+ xml_schema::boolean_simpl boolean_s;
+ xml_schema::unsigned_int_simpl unsigned_int_s;
+
+ person_simpl person_s;
+ superman_simpl superman_s;
+ batman_simpl batman_s;
+
+ person_s.serializers (string_s);
+ superman_s.serializers (string_s, boolean_s);
+ batman_s.serializers (string_s, boolean_s, unsigned_int_s);
+
+ // Serialize each item in the supermen catalog as a separate XML
+ // document.
+ //
+ for (supermen::const_iterator i = sm.begin (); i != sm.end (); ++i)
+ {
+ person& p = **i;
+ person_sskel* ps = 0;
+
+ switch (p.type ())
+ {
+ case person_type:
+ {
+ ps = &person_s;
+ break;
+ }
+ case superman_type:
+ {
+ ps = &superman_s;
+ break;
+ }
+ case batman_type:
+ {
+ ps = &batman_s;
+ break;
+ }
+ }
+
+ // Create a document serializer for this type. Note that we pass
+ // true as the third argument to indicate polymorphic serialization
+ // as well as the root element's static type as the last argument
+ // which is necessary if the actual root type can differ from its
+ // static type.
+ //
+ xml_schema::document_simpl doc_s (
+ *ps, "person", true, person_sskel::_static_type ());
+
+ doc_s.add_no_namespace_schema ("supermen.xsd");
+
+ ps->pre (p);
+ doc_s.serialize (std::cout);
+ ps->post ();
+
+ std::cout << endl
+ << endl;
+ }
+ }
+ catch (const xml_schema::serializer_exception& e)
+ {
+ cerr << "error: " << e.text () << endl;
+ return 1;
+ }
+ catch (const std::ios_base::failure&)
+ {
+ cerr << "error: write failure" << endl;
+ return 1;
+ }
+
+ return 0;
+}
diff --git a/examples/cxx/serializer/polyroot/makefile b/examples/cxx/serializer/polyroot/makefile
new file mode 100644
index 0000000..9427b4a
--- /dev/null
+++ b/examples/cxx/serializer/polyroot/makefile
@@ -0,0 +1,73 @@
+# file : examples/cxx/serializer/polyroot/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-simpl-mixin.cxx
+else
+cxx += supermen-simpl-tiein.cxx
+endif
+
+obj := $(addprefix $(out_base)/,$(cxx:.cxx=.o) $(xsd:.xsd=-sskel.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=-sskel.hxx) \
+ $(out_base)/$(xsd:.xsd=-sskel.ixx) \
+ $(out_base)/$(xsd:.xsd=-sskel.cxx)
+
+$(skel): xsde := $(out_root)/xsde/xsde
+$(skel): xsde_options += --generate-polymorphic \
+--type-map $(src_base)/supermen.map
+
+$(skel): $(out_root)/xsde/xsde $(src_base)/supermen.map
+
+$(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=-sskel.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/serializer/xsd-cxx.make)
+
+
+# Dependencies.
+#
+$(call import,$(src_root)/xsde/makefile)
+$(call import,$(src_root)/libxsde/xsde/makefile)
diff --git a/examples/cxx/serializer/polyroot/supermen-simpl-mixin.cxx b/examples/cxx/serializer/polyroot/supermen-simpl-mixin.cxx
new file mode 100644
index 0000000..b6ea058
--- /dev/null
+++ b/examples/cxx/serializer/polyroot/supermen-simpl-mixin.cxx
@@ -0,0 +1,35 @@
+// file : examples/cxx/serializer/polyroot/supermen-simpl-mixin.cxx
+// author : Boris Kolpackov <boris@codesynthesis.com>
+// copyright : not copyrighted - public domain
+
+#include "supermen-simpl-mixin.hxx"
+
+//
+//
+void person_simpl::
+pre (const person& p)
+{
+ person_ = &p;
+}
+
+std::string person_simpl::
+name ()
+{
+ return person_->name ();
+}
+
+//
+//
+bool superman_simpl::
+can_fly ()
+{
+ return static_cast<const superman*> (person_)->can_fly ();
+}
+
+//
+//
+unsigned int batman_simpl::
+wing_span ()
+{
+ return static_cast<const batman*> (person_)->wing_span ();
+}
diff --git a/examples/cxx/serializer/polyroot/supermen-simpl-mixin.hxx b/examples/cxx/serializer/polyroot/supermen-simpl-mixin.hxx
new file mode 100644
index 0000000..9f9f37c
--- /dev/null
+++ b/examples/cxx/serializer/polyroot/supermen-simpl-mixin.hxx
@@ -0,0 +1,35 @@
+// file : examples/cxx/serializer/polyroot/library-simpl-mixin.hxx
+// author : Boris Kolpackov <boris@codesynthesis.com>
+// copyright : not copyrighted - public domain
+
+#ifndef SUPERMEN_SIMPL_HXX
+#define SUPERMEN_SIMPL_HXX
+
+#include "supermen.hxx"
+#include "supermen-sskel.hxx"
+
+struct person_simpl: virtual person_sskel
+{
+ virtual void
+ pre (const person&);
+
+ virtual std::string
+ name ();
+
+protected:
+ const person* person_;
+};
+
+struct superman_simpl: virtual superman_sskel, person_simpl
+{
+ virtual bool
+ can_fly ();
+};
+
+struct batman_simpl: virtual batman_sskel, superman_simpl
+{
+ virtual unsigned int
+ wing_span ();
+};
+
+#endif // SUPERMEN_SIMPL_HXX
diff --git a/examples/cxx/serializer/polyroot/supermen-simpl-tiein.cxx b/examples/cxx/serializer/polyroot/supermen-simpl-tiein.cxx
new file mode 100644
index 0000000..f72e0f4
--- /dev/null
+++ b/examples/cxx/serializer/polyroot/supermen-simpl-tiein.cxx
@@ -0,0 +1,59 @@
+// file : examples/cxx/serializer/polyroot/supermen-simpl-tiein.cxx
+// author : Boris Kolpackov <boris@codesynthesis.com>
+// copyright : not copyrighted - public domain
+
+#include "supermen-simpl-tiein.hxx"
+
+//
+//
+void person_simpl::
+pre (const person& p)
+{
+ person_ = &p;
+}
+
+std::string person_simpl::
+name ()
+{
+ return person_->name ();
+}
+
+//
+//
+superman_simpl::
+superman_simpl ()
+ : superman_sskel (&base_impl_)
+{
+}
+
+bool superman_simpl::
+can_fly ()
+{
+ return superman_ ().can_fly ();
+}
+
+const superman& superman_simpl::
+superman_ ()
+{
+ return *static_cast<const superman*> (base_impl_.person_);
+}
+
+//
+//
+batman_simpl::
+batman_simpl ()
+ : batman_sskel (&base_impl_)
+{
+}
+
+unsigned int batman_simpl::
+wing_span ()
+{
+ return batman_ ().wing_span ();
+}
+
+const batman& batman_simpl::
+batman_ ()
+{
+ return static_cast<const batman&> (base_impl_.superman_ ());
+}
diff --git a/examples/cxx/serializer/polyroot/supermen-simpl-tiein.hxx b/examples/cxx/serializer/polyroot/supermen-simpl-tiein.hxx
new file mode 100644
index 0000000..e67e7f4
--- /dev/null
+++ b/examples/cxx/serializer/polyroot/supermen-simpl-tiein.hxx
@@ -0,0 +1,53 @@
+// file : examples/cxx/serializer/polyroot/supermen-simpl-tiein.hxx
+// author : Boris Kolpackov <boris@codesynthesis.com>
+// copyright : not copyrighted - public domain
+
+#ifndef SUPERMEN_SIMPL_HXX
+#define SUPERMEN_SIMPL_HXX
+
+#include "supermen.hxx"
+#include "supermen-sskel.hxx"
+
+struct person_simpl: person_sskel
+{
+ virtual void
+ pre (const person&);
+
+ virtual std::string
+ name ();
+
+ // Derived serializers need access to this variable.
+ //
+public:
+ const person* person_;
+};
+
+struct superman_simpl: superman_sskel
+{
+ superman_simpl ();
+
+ virtual bool
+ can_fly ();
+
+ const superman&
+ superman_ ();
+
+private:
+ person_simpl base_impl_;
+};
+
+struct batman_simpl: batman_sskel
+{
+ batman_simpl ();
+
+ virtual unsigned int
+ wing_span ();
+
+ const batman&
+ batman_ ();
+
+private:
+ superman_simpl base_impl_;
+};
+
+#endif // SUPERMEN_SIMPL_HXX
diff --git a/examples/cxx/serializer/polyroot/supermen.hxx b/examples/cxx/serializer/polyroot/supermen.hxx
new file mode 100644
index 0000000..7987a0d
--- /dev/null
+++ b/examples/cxx/serializer/polyroot/supermen.hxx
@@ -0,0 +1,129 @@
+// file : examples/cxx/serializer/polyroot/supermen.hxx
+// author : Boris Kolpackov <boris@codesynthesis.com>
+// copyright : not copyrighted - public domain
+
+#ifndef SUPERMEN_HXX
+#define SUPERMEN_HXX
+
+#include <string>
+#include <vector>
+
+// Custom type id. We could also use standard C++ typeid/type_info
+// if it is available.
+//
+enum type_id
+{
+ person_type,
+ superman_type,
+ batman_type
+};
+
+//
+//
+struct person
+{
+ virtual
+ ~person ()
+ {
+ }
+
+ person (const std::string& name)
+ : name_ (name)
+ {
+ }
+
+ const std::string&
+ name () const
+ {
+ return name_;
+ }
+
+ void
+ name (const std::string& n)
+ {
+ name_ = n;
+ }
+
+ virtual type_id
+ type () const
+ {
+ return person_type;
+ }
+
+private:
+ std::string name_;
+};
+
+//
+//
+struct superman: person
+{
+ superman (const std::string& name, bool can_fly)
+ : person (name), can_fly_ (can_fly)
+ {
+ }
+
+ bool
+ can_fly () const
+ {
+ return can_fly_;
+ }
+
+ void
+ can_fly (bool cf)
+ {
+ can_fly_ = cf;
+ }
+
+ virtual type_id
+ type () const
+ {
+ return superman_type;
+ }
+
+private:
+ bool can_fly_;
+};
+
+struct batman: superman
+{
+ batman (const std::string& name, unsigned int wing_span)
+ : superman (name, true), wing_span_ (wing_span)
+ {
+ }
+
+ unsigned int
+ wing_span () const
+ {
+ return wing_span_;
+ }
+
+ void
+ wing_span (unsigned int ws)
+ {
+ wing_span_ = ws;
+ }
+
+ virtual type_id
+ type () const
+ {
+ return batman_type;
+ }
+
+private:
+ unsigned int wing_span_;
+};
+
+// Poor man's polymorphic sequence which also assumes ownership of the
+// elements.
+//
+struct supermen: std::vector<person*>
+{
+ ~supermen ()
+ {
+ for (iterator i = begin (); i != end (); ++i)
+ delete *i;
+ }
+};
+
+#endif // SUPERMEN_HXX
diff --git a/examples/cxx/serializer/polyroot/supermen.map b/examples/cxx/serializer/polyroot/supermen.map
new file mode 100644
index 0000000..53b1097
--- /dev/null
+++ b/examples/cxx/serializer/polyroot/supermen.map
@@ -0,0 +1,9 @@
+# file : examples/cxx/serializer/polyroot/supermen.map
+# author : Boris Kolpackov <boris@codesynthesis.com>
+# copyright : not copyrighted - public domain
+
+include "supermen.hxx";
+
+person "const ::person&";
+superman "const ::person&";
+batman "const ::person&";
diff --git a/examples/cxx/serializer/polyroot/supermen.xsd b/examples/cxx/serializer/polyroot/supermen.xsd
new file mode 100644
index 0000000..3d1d4a8
--- /dev/null
+++ b/examples/cxx/serializer/polyroot/supermen.xsd
@@ -0,0 +1,41 @@
+<?xml version="1.0"?>
+
+<!--
+
+file : examples/cxx/serializer/polyroot/schema.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:schema>
diff --git a/examples/cxx/serializer/wildcard/README b/examples/cxx/serializer/wildcard/README
new file mode 100644
index 0000000..831a2d4
--- /dev/null
+++ b/examples/cxx/serializer/wildcard/README
@@ -0,0 +1,37 @@
+This example shows how to serialize XML data matched by XML Schema
+wildcards (any and anyAttribute) using the Embedded C++/Serializer
+mapping.
+
+The example consists of the following files:
+
+email.xsd
+ XML Schema which describes a simple email format with the
+ extensible envelope type.
+
+email.hxx
+ C++ types that describe the email format defined in email.xsd.
+ These are hand-written.
+
+email.map
+ Type map. It maps XML Schema types defined in email.xsd to C++
+ types defined in email.hxx.
+
+email-sskel.hxx
+email-sskel.cxx
+ Serializer skeletons generated by XSD/e from email.xsd and
+ email.map.
+
+driver.cxx
+ Serializer implementations and a driver for the example. The
+ serializer implementations serialize the in-memory object model
+ defined in email.hxx to XML. The driver first constructs a sample
+ email object using the types from email.hxx. It then creates a
+ serializer instance using the serializer implementations mentioned
+ above and a couple of predefined serializers for the XML Schema
+ built-in types. Finally, it invokes this serializer instance to
+ serialize the sample email object to an XML document which is
+ printed to STDOUT.
+
+To run the example simply execute:
+
+$ ./driver
diff --git a/examples/cxx/serializer/wildcard/driver.cxx b/examples/cxx/serializer/wildcard/driver.cxx
new file mode 100644
index 0000000..7feb13a
--- /dev/null
+++ b/examples/cxx/serializer/wildcard/driver.cxx
@@ -0,0 +1,410 @@
+// file : examples/cxx/serializer/wildcard/driver.cxx
+// author : Boris Kolpackov <boris@codesynthesis.com>
+// copyright : not copyrighted - public domain
+
+#include <iostream>
+
+#include "email-sskel.hxx"
+
+#ifndef XSDE_REUSE_STYLE_TIEIN
+# error this example requires the tiein serializer reuse support
+#endif
+
+using namespace std;
+
+namespace email
+{
+ struct binary_simpl: binary_sskel
+ {
+ // Indicate to base64_binary_simpl that we want it to release
+ // the buffer passed via pre().
+ //
+ binary_simpl ()
+ : binary_sskel (&base_impl_), base_impl_ (true)
+ {
+ }
+
+ virtual void
+ pre (const binary* bin)
+ {
+ using namespace xml_schema;
+
+ bin_ = bin;
+ buffer* buf = new buffer (bin->data (), bin->size ());
+ base_impl_.pre (buf);
+ }
+
+ virtual std::string
+ name ()
+ {
+ return bin_->name ();
+ }
+
+ virtual std::string
+ mime ()
+ {
+ return bin_->mime ();
+ }
+
+ private:
+ xml_schema::base64_binary_simpl base_impl_;
+ const binary* bin_;
+ };
+
+ struct envelope_simpl: envelope_sskel
+ {
+ envelope_simpl (xml_schema::string_simpl& text_s,
+ binary_sskel& bin_s,
+ xml_schema::unsigned_int_simpl& uint_s)
+ : text_s_ (text_s), bin_s_ (bin_s), uint_s_ (uint_s)
+ {
+ }
+
+ virtual void
+ pre (const envelope& env)
+ {
+ env_ = &env;
+ tid_set_ = false;
+ i_ = env_->begin_body ();
+ }
+
+ // Attributes.
+ //
+ virtual bool
+ any_attribute_next ()
+ {
+ return !tid_set_;
+ }
+
+ virtual void
+ any_attribute (std::string& ns, std::string& name)
+ {
+ ns = "http://www.codesynthesis.com/email";
+ name = "thread-id";
+ }
+
+ virtual void
+ serialize_any_attribute ()
+ {
+ // This function is where we perform the actual wildcard
+ // serialization.
+ //
+ xml_schema::serializer_context& ctx = _context ();
+
+#if defined(XSDE_EXCEPTIONS) && !defined(XSDE_SERIALIZER_VALIDATION)
+
+ uint_s_.pre (env_->thread_id ());
+ uint_s_._pre_impl (ctx);
+ uint_s_._serialize_content ();
+ uint_s_._post_impl ();
+ uint_s_.post ();
+#else
+ // If we are not using exceptions or XML Schema validation
+ // is enabled then we need to check for the error condition
+ // and, if the (user) error was set in pre() or post(),
+ // also copy the error code to the context. The _error_type()
+ // function returns non-0 value if there an error pending.
+ // The _copy_error() functions copies the error state to
+ // the context.
+
+ uint_s_.pre (env_->thread_id ());
+
+#ifndef XSDE_EXCEPTIONS
+ if (uint_s_._error_type ())
+ uint_s_._copy_error (ctx);
+
+ if (ctx.error_type ())
+ return;
+#endif
+ uint_s_._pre_impl (ctx);
+
+ if (ctx.error_type ())
+ return;
+
+ uint_s_._serialize_content ();
+
+ if (ctx.error_type ())
+ return;
+
+ uint_s_._post_impl ();
+
+ if (ctx.error_type ())
+ return;
+
+ uint_s_.post ();
+
+#ifndef XSDE_EXCEPTIONS
+ if (uint_s_._error_type ())
+ uint_s_._copy_error (ctx);
+
+ if (_error_type ())
+ return;
+#endif
+#endif
+
+ tid_set_ = true;
+ }
+
+ // Elements.
+ //
+ virtual std::string
+ to ()
+ {
+ return env_->to ();
+ }
+
+ virtual std::string
+ from ()
+ {
+ return env_->from ();
+ }
+
+ virtual std::string
+ subject ()
+ {
+ return env_->subject ();
+ }
+
+ virtual bool
+ any_next ()
+ {
+ // See if there is a body that we know how to serialize.
+ //
+ for (; i_ != env_->end_body (); ++i_)
+ {
+ body_type t = (*i_)->type ();
+
+ if (t == email::text_body || t == email::binary_body)
+ break;
+ }
+
+ return i_ != env_->end_body ();
+ }
+
+ virtual void
+ any (std::string& ns, std::string& name)
+ {
+ ns = "http://www.codesynthesis.com/email";
+
+ switch ((*i_)->type ())
+ {
+ case email::text_body:
+ {
+ name = "text";
+ break;
+ }
+ case email::binary_body:
+ {
+ name = "binary";
+ break;
+ }
+ }
+ }
+
+ virtual void
+ serialize_any ()
+ {
+ const body* b = *i_++;
+ xml_schema::serializer_context& ctx = _context ();
+
+ switch (b->type ())
+ {
+ case email::text_body:
+ {
+ // For more information on what's going here, see the
+ // serialize_any_attribute() function above.
+ //
+#if defined(XSDE_EXCEPTIONS) && !defined(XSDE_SERIALIZER_VALIDATION)
+
+ text_s_.pre (static_cast<const text*> (b)->content ());
+ text_s_._pre_impl (ctx);
+ text_s_._serialize_content ();
+ text_s_._post_impl ();
+ text_s_.post ();
+#else
+
+ text_s_.pre (static_cast<const text*> (b)->content ());
+
+#ifndef XSDE_EXCEPTIONS
+ if (text_s_._error_type ())
+ text_s_._copy_error (ctx);
+
+ if (ctx.error_type ())
+ return;
+#endif
+ text_s_._pre_impl (ctx);
+
+ if (ctx.error_type ())
+ return;
+
+ text_s_._serialize_content ();
+
+ if (ctx.error_type ())
+ return;
+
+ text_s_._post_impl ();
+
+ if (ctx.error_type ())
+ return;
+
+ text_s_.post ();
+
+#ifndef XSDE_EXCEPTIONS
+ if (text_s_._error_type ())
+ text_s_._copy_error (ctx);
+
+ if (ctx.error_type ())
+ return;
+#endif
+#endif
+ break;
+ }
+ case email::binary_body:
+ {
+ // For more information on what's going here, see the
+ // serialize_any_attribute() function above. Note also
+ // that in this case we also call _serialize_attributes
+ // since binary is a complex type.
+ //
+
+#if defined(XSDE_EXCEPTIONS) && !defined(XSDE_SERIALIZER_VALIDATION)
+ bin_s_.pre (static_cast<const binary*> (b));
+ bin_s_._pre_impl (ctx);
+ bin_s_._serialize_attributes ();
+ bin_s_._serialize_content ();
+ bin_s_._post_impl ();
+ bin_s_.post ();
+#else
+ bin_s_.pre (static_cast<const binary*> (b));
+
+#ifndef XSDE_EXCEPTIONS
+ if (bin_s_._error_type ())
+ bin_s_._copy_error (ctx);
+
+ if (ctx.error_type ())
+ return;
+#endif
+ bin_s_._pre_impl (ctx);
+
+ if (ctx.error_type ())
+ return;
+
+ bin_s_._serialize_attributes ();
+
+ if (ctx.error_type ())
+ return;
+
+ bin_s_._serialize_content ();
+
+ if (ctx.error_type ())
+ return;
+
+ bin_s_._post_impl ();
+
+ if (ctx.error_type ())
+ return;
+
+ bin_s_.post ();
+
+#ifndef XSDE_EXCEPTIONS
+ if (bin_s_._error_type ())
+ bin_s_._copy_error (ctx);
+
+ if (ctx.error_type ())
+ return;
+#endif
+#endif
+ break;
+ }
+ }
+ }
+
+ // If we need to be able to reset and reuse the serializer
+ // after an error then we also need to override _reset() and
+ // reset the serializers that are used to handle wildcards.
+ // Note that you always need to call _reset() from the base.
+ //
+ virtual void
+ _reset ()
+ {
+ envelope_sskel::_reset ();
+
+ text_s_._reset ();
+ bin_s_._reset ();
+ uint_s_._reset ();
+ }
+
+ private:
+ // Serializers used in wildcard content serialization.
+ //
+ xml_schema::string_simpl& text_s_;
+ binary_sskel& bin_s_;
+ xml_schema::unsigned_int_simpl& uint_s_;
+
+ const envelope* env_;
+ bool tid_set_;
+ envelope::body_iterator i_;
+ };
+}
+
+int
+main ()
+{
+ try
+ {
+ using namespace email;
+
+ // Create a sample email with a text body and two (fake) pictures.
+ //
+ envelope env ("Jane Doe <jane@doe.com>",
+ "John Doe <john@doe.com>",
+ "Surfing pictures",
+ 123); // thread id
+
+ env.add_body (new text ("Hi Jane,\n"
+ "Here are cool pictures of me surfing.\n\n"
+ "Cheers,\n"
+ "John"));
+
+ env.add_body (new binary ("pic1.jpg", "image/jpeg", "abc123", 6));
+ env.add_body (new binary ("pic2.jpg", "image/jpeg", "123abc", 6));
+
+
+ // Construct the serializer.
+ //
+ xml_schema::string_simpl string_s;
+ xml_schema::unsigned_int_simpl uint_s;
+
+ binary_simpl binary_s;
+ envelope_simpl envelope_s (string_s, binary_s, uint_s);
+
+ binary_s.serializers (string_s, string_s);
+ envelope_s.serializers (string_s, string_s, string_s);
+
+ // Serialize the sample email to XML document.
+ //
+ xml_schema::document_simpl doc_s (
+ envelope_s,
+ "http://www.codesynthesis.com/email",
+ "message");
+
+ doc_s.add_prefix ("eml", "http://www.codesynthesis.com/email");
+ doc_s.add_schema ("http://www.codesynthesis.com/email", "email.xsd");
+
+ envelope_s.pre (env);
+ doc_s.serialize (cout);
+ envelope_s.post ();
+ }
+ catch (const xml_schema::serializer_exception& e)
+ {
+ cerr << "error: " << e.text () << endl;
+ return 1;
+ }
+ catch (const std::ios_base::failure&)
+ {
+ cerr << "error: write failure" << endl;
+ return 1;
+ }
+
+ return 0;
+}
diff --git a/examples/cxx/serializer/wildcard/email.hxx b/examples/cxx/serializer/wildcard/email.hxx
new file mode 100644
index 0000000..6cf76da
--- /dev/null
+++ b/examples/cxx/serializer/wildcard/email.hxx
@@ -0,0 +1,194 @@
+// file : examples/cxx/serializer/wildcard/email.hxx
+// author : Boris Kolpackov <boris@codesynthesis.com>
+// copyright : not copyrighted - public domain
+
+#ifndef EMAIL_HXX
+#define EMAIL_HXX
+
+#include <string>
+#include <vector>
+#include <cstddef> // std::size_t
+#include <cstring> // std::memcpy
+
+namespace email
+{
+ //
+ //
+ enum body_type
+ {
+ text_body,
+ binary_body
+ };
+
+ struct body
+ {
+ virtual body_type
+ type () const = 0;
+
+ virtual
+ ~body ()
+ {
+ }
+ };
+
+ //
+ //
+ struct text: body
+ {
+ text (const std::string& content)
+ : content_ (content)
+ {
+ }
+
+ virtual body_type
+ type () const
+ {
+ return text_body;
+ }
+
+ const std::string&
+ content () const
+ {
+ return content_;
+ }
+
+ private:
+ std::string content_;
+ };
+
+ //
+ //
+ struct binary: body
+ {
+ binary (const std::string& name,
+ const std::string& mime,
+ const char* data,
+ std::size_t size)
+ : name_ (name), mime_ (mime), data_ (0), size_ (size)
+ {
+ if (size_ != 0)
+ {
+ data_ = new char[size_];
+ std::memcpy (data_, data, size_);
+ }
+ }
+
+ virtual
+ ~binary ()
+ {
+ delete[] data_;
+ }
+
+ virtual body_type
+ type () const
+ {
+ return binary_body;
+ }
+
+ const std::string&
+ name () const
+ {
+ return name_;
+ }
+
+ const std::string&
+ mime () const
+ {
+ return mime_;
+ }
+
+ const char*
+ data () const
+ {
+ return data_;
+ }
+
+ std::size_t
+ size () const
+ {
+ return size_;
+ }
+
+ private:
+ std::string name_;
+ std::string mime_;
+ char* data_;
+ std::size_t size_;
+ };
+
+ //
+ //
+ struct envelope
+ {
+ envelope (const std::string& to,
+ const std::string& from,
+ const std::string& subject,
+ unsigned int thread_id)
+ : to_ (to), from_ (from), subject_ (subject), thread_id_ (thread_id)
+ {
+ }
+
+ const std::string&
+ to () const
+ {
+ return to_;
+ }
+
+ const std::string&
+ from () const
+ {
+ return from_;
+ }
+
+ const std::string&
+ subject () const
+ {
+ return subject_;
+ }
+
+ unsigned int
+ thread_id () const
+ {
+ return thread_id_;
+ }
+
+ // Assumes ownership of the passed object.
+ //
+ void
+ add_body (body* b)
+ {
+ bodies_.push_back (b);
+ }
+
+ typedef std::vector<body*> bodies;
+ typedef bodies::const_iterator body_iterator;
+
+ body_iterator
+ begin_body () const
+ {
+ return bodies_.begin ();
+ }
+
+ body_iterator
+ end_body () const
+ {
+ return bodies_.end ();
+ }
+
+ ~envelope ()
+ {
+ for (body_iterator i = begin_body (); i != end_body (); ++i)
+ delete *i;
+ }
+
+ private:
+ const std::string to_;
+ const std::string from_;
+ const std::string subject_;
+ unsigned int thread_id_;
+
+ bodies bodies_;
+ };
+}
+
+#endif // EMAIL_HXX
diff --git a/examples/cxx/serializer/wildcard/email.map b/examples/cxx/serializer/wildcard/email.map
new file mode 100644
index 0000000..fadafb2
--- /dev/null
+++ b/examples/cxx/serializer/wildcard/email.map
@@ -0,0 +1,12 @@
+# file : examples/cxx/serializer/wildcard/email.map
+# author : Boris Kolpackov <boris@codesynthesis.com>
+# copyright : not copyrighted - public domain
+
+namespace http://www.codesynthesis.com/email
+{
+ include "email.hxx";
+
+ text "const text*";
+ binary "const binary*";
+ envelope "const envelope&";
+}
diff --git a/examples/cxx/serializer/wildcard/email.xsd b/examples/cxx/serializer/wildcard/email.xsd
new file mode 100644
index 0000000..bf61589
--- /dev/null
+++ b/examples/cxx/serializer/wildcard/email.xsd
@@ -0,0 +1,51 @@
+<?xml version="1.0"?>
+
+<!--
+
+file : examples/cxx/serializer/wildcard/email.xsd
+author : Boris Kolpackov <boris@codesynthesis.com>
+copyright : not copyrighted - public domain
+
+-->
+
+<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema"
+ xmlns:eml="http://www.codesynthesis.com/email"
+ targetNamespace="http://www.codesynthesis.com/email">
+
+ <!-- Predefined envolop body types. -->
+
+ <xsd:element name="text" type="xsd:string"/>
+
+ <xsd:complexType name="binary">
+ <xsd:simpleContent>
+ <xsd:extension base="xsd:base64Binary">
+ <xsd:attribute name="name" type="xsd:string" use="required"/>
+ <xsd:attribute name="mime" type="xsd:string" use="required"/>
+ </xsd:extension>
+ </xsd:simpleContent>
+ </xsd:complexType>
+
+ <xsd:element name="binary" type="eml:binary"/>
+
+ <!-- Predefined envelop attributes. -->
+
+ <xsd:attribute name="thread-id" type="xsd:unsignedInt"/>
+
+
+ <xsd:complexType name="envelope">
+ <xsd:sequence>
+ <xsd:element name="to" type="xsd:string"/>
+ <xsd:element name="from" type="xsd:string"/>
+ <xsd:element name="subject" type="xsd:string"/>
+
+ <!-- Extensible envelope body. -->
+
+ <xsd:any namespace="##targetNamespace" processContents="strict"
+ maxOccurs="unbounded" />
+ </xsd:sequence>
+ <xsd:anyAttribute namespace="##targetNamespace" processContents="strict"/>
+ </xsd:complexType>
+
+ <xsd:element name="message" type="eml:envelope"/>
+
+</xsd:schema>
diff --git a/examples/cxx/serializer/wildcard/makefile b/examples/cxx/serializer/wildcard/makefile
new file mode 100644
index 0000000..a6f881b
--- /dev/null
+++ b/examples/cxx/serializer/wildcard/makefile
@@ -0,0 +1,66 @@
+# file : examples/cxx/serializer/wildcard/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 := email.xsd
+cxx := driver.cxx
+
+obj := $(addprefix $(out_base)/,$(cxx:.cxx=.o) $(xsd:.xsd=-sskel.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=-sskel.hxx) \
+ $(out_base)/$(xsd:.xsd=-sskel.ixx) \
+ $(out_base)/$(xsd:.xsd=-sskel.cxx)
+
+$(skel): xsde := $(out_root)/xsde/xsde
+$(skel): xsde_options += --type-map $(src_base)/email.map
+
+$(skel): $(out_root)/xsde/xsde $(src_base)/email.map
+
+$(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=-sskel.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/serializer/xsd-cxx.make)
+
+
+# Dependencies.
+#
+$(call import,$(src_root)/xsde/makefile)
+$(call import,$(src_root)/libxsde/xsde/makefile)