From 707cc94fe52463870a9c6c8e2e66eaaa389e601d Mon Sep 17 00:00:00 2001 From: Boris Kolpackov Date: Tue, 24 Feb 2009 15:16:26 +0200 Subject: Start tracking XSD/e with git after version 3.0.0 --- examples/cxx/serializer/wildcard/README | 37 +++ examples/cxx/serializer/wildcard/driver.cxx | 410 ++++++++++++++++++++++++++++ examples/cxx/serializer/wildcard/email.hxx | 194 +++++++++++++ examples/cxx/serializer/wildcard/email.map | 12 + examples/cxx/serializer/wildcard/email.xsd | 51 ++++ examples/cxx/serializer/wildcard/makefile | 66 +++++ 6 files changed, 770 insertions(+) create mode 100644 examples/cxx/serializer/wildcard/README create mode 100644 examples/cxx/serializer/wildcard/driver.cxx create mode 100644 examples/cxx/serializer/wildcard/email.hxx create mode 100644 examples/cxx/serializer/wildcard/email.map create mode 100644 examples/cxx/serializer/wildcard/email.xsd create mode 100644 examples/cxx/serializer/wildcard/makefile (limited to 'examples/cxx/serializer/wildcard') 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 +// copyright : not copyrighted - public domain + +#include + +#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 (b)->content ()); + text_s_._pre_impl (ctx); + text_s_._serialize_content (); + text_s_._post_impl (); + text_s_.post (); +#else + + text_s_.pre (static_cast (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 (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 (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 ", + "John Doe ", + "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 +// copyright : not copyrighted - public domain + +#ifndef EMAIL_HXX +#define EMAIL_HXX + +#include +#include +#include // std::size_t +#include // 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 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 +# 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 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 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 +# 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) -- cgit v1.1