aboutsummaryrefslogtreecommitdiff
path: root/examples/cxx/serializer/wildcard
diff options
context:
space:
mode:
Diffstat (limited to 'examples/cxx/serializer/wildcard')
-rw-r--r--examples/cxx/serializer/wildcard/README37
-rw-r--r--examples/cxx/serializer/wildcard/driver.cxx410
-rw-r--r--examples/cxx/serializer/wildcard/email.hxx194
-rw-r--r--examples/cxx/serializer/wildcard/email.map12
-rw-r--r--examples/cxx/serializer/wildcard/email.xsd51
-rw-r--r--examples/cxx/serializer/wildcard/makefile66
6 files changed, 770 insertions, 0 deletions
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)