diff options
Diffstat (limited to 'examples/cxx/serializer/wildcard/driver.cxx')
-rw-r--r-- | examples/cxx/serializer/wildcard/driver.cxx | 410 |
1 files changed, 410 insertions, 0 deletions
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; +} |