diff options
author | Boris Kolpackov <boris@codesynthesis.com> | 2009-02-24 15:16:26 +0200 |
---|---|---|
committer | Boris Kolpackov <boris@codesynthesis.com> | 2009-02-24 15:16:26 +0200 |
commit | 707cc94fe52463870a9c6c8e2e66eaaa389e601d (patch) | |
tree | 13e10ff28bf4455d915f9d59b401bdbb62a393cb /examples/cxx/serializer |
Start tracking XSD/e with git after version 3.0.03.0.0
Diffstat (limited to 'examples/cxx/serializer')
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) |