From bce9d5a76072ec697ef69021818aa68709036da5 Mon Sep 17 00:00:00 2001 From: Boris Kolpackov Date: Mon, 16 Mar 2009 08:16:43 +0200 Subject: Add support for type customization in C++/Hybrid examples/cxx/hybrid/custom/wildcard/: new example --- examples/cxx/hybrid/README | 6 + examples/cxx/hybrid/custom/README | 7 + examples/cxx/hybrid/custom/makefile | 45 +++++ examples/cxx/hybrid/custom/wildcard/README | 83 +++++++++ examples/cxx/hybrid/custom/wildcard/body.cxx | 20 +++ examples/cxx/hybrid/custom/wildcard/body.hxx | 76 +++++++++ examples/cxx/hybrid/custom/wildcard/driver.cxx | 185 +++++++++++++++++++++ examples/cxx/hybrid/custom/wildcard/email.xml | 31 ++++ examples/cxx/hybrid/custom/wildcard/email.xsd | 45 +++++ .../cxx/hybrid/custom/wildcard/envelope-pimpl.cxx | 100 +++++++++++ .../cxx/hybrid/custom/wildcard/envelope-pimpl.hxx | 78 +++++++++ .../cxx/hybrid/custom/wildcard/envelope-simpl.cxx | 137 +++++++++++++++ .../cxx/hybrid/custom/wildcard/envelope-simpl.hxx | 67 ++++++++ examples/cxx/hybrid/custom/wildcard/envelope.cxx | 11 ++ examples/cxx/hybrid/custom/wildcard/envelope.hxx | 39 +++++ examples/cxx/hybrid/custom/wildcard/makefile | 124 ++++++++++++++ examples/cxx/hybrid/makefile | 4 +- examples/cxx/hybrid/wildcard/README | 13 +- examples/cxx/hybrid/wildcard/envelope-pimpl.hxx | 2 +- 19 files changed, 1065 insertions(+), 8 deletions(-) create mode 100644 examples/cxx/hybrid/custom/README create mode 100644 examples/cxx/hybrid/custom/makefile create mode 100644 examples/cxx/hybrid/custom/wildcard/README create mode 100644 examples/cxx/hybrid/custom/wildcard/body.cxx create mode 100644 examples/cxx/hybrid/custom/wildcard/body.hxx create mode 100644 examples/cxx/hybrid/custom/wildcard/driver.cxx create mode 100644 examples/cxx/hybrid/custom/wildcard/email.xml create mode 100644 examples/cxx/hybrid/custom/wildcard/email.xsd create mode 100644 examples/cxx/hybrid/custom/wildcard/envelope-pimpl.cxx create mode 100644 examples/cxx/hybrid/custom/wildcard/envelope-pimpl.hxx create mode 100644 examples/cxx/hybrid/custom/wildcard/envelope-simpl.cxx create mode 100644 examples/cxx/hybrid/custom/wildcard/envelope-simpl.hxx create mode 100644 examples/cxx/hybrid/custom/wildcard/envelope.cxx create mode 100644 examples/cxx/hybrid/custom/wildcard/envelope.hxx create mode 100644 examples/cxx/hybrid/custom/wildcard/makefile (limited to 'examples') diff --git a/examples/cxx/hybrid/README b/examples/cxx/hybrid/README index 2008450..d23c10d 100644 --- a/examples/cxx/hybrid/README +++ b/examples/cxx/hybrid/README @@ -36,6 +36,12 @@ compositors Shows how to create, access, and modify object models with complex nested choice and sequence compositors. +custom/ + A collection of examples that show how to customize the C++/Hybrid + object model by using custom C++ classes instead of or in addition + to the generated ones. See the accompanying README file for an + overview of each example in this directory. + binary/ A collection of examples that show how to serialize the object model into a number of predefined and custom binary formats. diff --git a/examples/cxx/hybrid/custom/README b/examples/cxx/hybrid/custom/README new file mode 100644 index 0000000..bf0bfac --- /dev/null +++ b/examples/cxx/hybrid/custom/README @@ -0,0 +1,7 @@ +This directory contains a number of examples that show how to customize +the C++/Hybrid object model. The following list gives an overview of +each example: + +wildcard + Shows how to parse, store in the object model, and serialize XML data + matched by XML Schema wildcards (any and anyAttribute). diff --git a/examples/cxx/hybrid/custom/makefile b/examples/cxx/hybrid/custom/makefile new file mode 100644 index 0000000..856a9fe --- /dev/null +++ b/examples/cxx/hybrid/custom/makefile @@ -0,0 +1,45 @@ +# file : examples/cxx/hybrid/custom/makefile +# author : Boris Kolpackov +# 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 + +all_examples := wildcard +build_examples := + +ifeq ($(xsde_iostream),y) +ifeq ($(xsde_exceptions),y) + +build_examples += wildcard + +endif +endif + +default := $(out_base)/ +dist := $(out_base)/.dist +dist-win := $(out_base)/.dist-win +clean := $(out_base)/.clean + +.PHONY: $(default) $(dist) $(dist-win) $(clean) + +$(default): $(addprefix $(out_base)/,$(addsuffix /,$(build_examples))) +$(clean): $(addprefix $(out_base)/,$(addsuffix /.clean,$(build_examples))) + +# Dist. +# +$(dist) $(dist-win): path := $(subst $(src_root)/,,$(src_base)) + +$(dist): $(addprefix $(out_base)/,$(addsuffix /.dist,$(all_examples))) + $(call install-data,$(src_base)/README,$(dist_prefix)/$(path)/README) + +$(dist-win): $(addprefix $(out_base)/,$(addsuffix /.dist-win,$(all_examples))) + $(call install-data,$(src_base)/README,$(dist_prefix)/$(path)/README.txt) + $(call message,,unix2dos $(dist_prefix)/$(path)/README.txt) + + +ifneq ($(filter $(MAKECMDGOALS),dist dist-win),) +$(foreach e,$(all_examples),$(call import,$(src_base)/$e/makefile)) +else +$(foreach e,$(build_examples),$(call import,$(src_base)/$e/makefile)) +endif diff --git a/examples/cxx/hybrid/custom/wildcard/README b/examples/cxx/hybrid/custom/wildcard/README new file mode 100644 index 0000000..e8ef1b8 --- /dev/null +++ b/examples/cxx/hybrid/custom/wildcard/README @@ -0,0 +1,83 @@ +This example shows how to parse, store in the object model, and serialize +XML data matched by XML Schema wildcards (any and anyAttribute) using the +Embedded C++/Hybrid. + +This example uses the object model as well as parser and serializer +customization mechanisms provided by the C++/Hybrid mapping. For more +information, see Section 4.8, "Customizing the Object Model" and Section +6.1, "Customizing Parsers and Serializers" in the Embedded C++/Hybrid +Mapping Getting Started Guide. + +The example consists of the following files: + +email.xsd + XML Schema which describes a simple email format with the + extensible envelope type. + +email.xml + Sample email message. + +email.hxx +email.cxx + +email-pskel.hxx +email-pskel.cxx +email-pimpl.hxx +email-pimpl.cxx + +email-pskel.hxx +email-pskel.cxx +email-pimpl.hxx +email-pimpl.cxx + Object model (the first pair of files), parser skeletons (the + second pair), parser implementations (the third pair), serializer + skeletons (the fourth pair), and serializer implementations (the + fifth pair). These files are generated by the XSD/e compiler from + email.xsd. The --generate-parser, --generate-serializer, and + --generate-aggregate options were used to request the generation of + the parsing and serialization code. The --custom-type option was + used to customize the the envelope class in the object model. The + --custom-parser option was used to customize the envelope_pimpl + parser implementation. The --custom-serializer option was used to + customize the envelope_simpl serializer implementation. Finally, + the --hxx-epilogue option was used to include body.hxx (see below) + at the end of the generated object model header file. + +body.hxx +body.cxx + Implementation of the body class. It is used to store the wildcard + data in the body sequence of the customized envelope class. + +envelope.hxx +envelope.cxx + Custom envelope type. It uses the generated version as a base and + adds a data member as well as accessor and modifier functions for + the wildcard content. + +envelope-pimpl.hxx +envelope-pimpl.cxx + Custom envelope parser implementation. It uses the implementation + generated by the XSD/e compiler as a base and overrides the wildcard + callbacks to parse the wildcard content and store in the body sequence + of the customized envelope object. + +envelope-simpl.hxx +envelope-simpl.cxx + Custom envelope serializer implementation. It uses the implementation + generated by the XSD/e compiler as a base and overrides the wildcard + callbacks to serialize the wildcard content stored in the body sequence + of the customized envelope object. + +driver.cxx + Driver for the example. It first calls the parser that constructs the + email object from the input XML file. It then prints the content of + the email to STDERR. Finally, the driver creates a reply email and + calls the serializer to serialize it to XML. + +To run the example on the sample XML instance document simply execute: + +$ ./driver email.xml + +The example reads from STDIN if input file is not specified: + +$ ./driver +// copyright : not copyrighted - public domain + +#include "body.hxx" + +namespace email +{ + void body:: + body_type (body::type t) + { + if (body_type_ == type_binary) + { + delete binary_; + binary_ = 0; + } + + body_type_ = t; + } +} diff --git a/examples/cxx/hybrid/custom/wildcard/body.hxx b/examples/cxx/hybrid/custom/wildcard/body.hxx new file mode 100644 index 0000000..504e3ca --- /dev/null +++ b/examples/cxx/hybrid/custom/wildcard/body.hxx @@ -0,0 +1,76 @@ +// file : examples/cxx/hybrid/custom/wildcard/body.hxx +// author : Boris Kolpackov +// copyright : not copyrighted - public domain + +#ifndef BODY_HXX +#define BODY_HXX + +#include "email.hxx" + +namespace email +{ + // Custom email body type which can hold text or binary. + // + class body + { + public: + enum type + { + type_none, + type_text, + type_binary + }; + + body () + : body_type_ (type_none), binary_ (0) + { + } + + ~body () + { + body_type (type_none); + } + + type + body_type () const + { + return body_type_; + } + + const std::string& + text () const + { + return text_; + } + + void + text (const std::string& t) + { + body_type (type_text); + text_ = t; + } + + const email::binary& + binary () const + { + return *binary_; + } + + void + binary (email::binary* b) + { + body_type (type_binary); + binary_ = b; + } + + private: + void + body_type (type t); + + type body_type_; + std::string text_; + email::binary* binary_; + }; +} + +#endif // BODY_HXX diff --git a/examples/cxx/hybrid/custom/wildcard/driver.cxx b/examples/cxx/hybrid/custom/wildcard/driver.cxx new file mode 100644 index 0000000..02870fa --- /dev/null +++ b/examples/cxx/hybrid/custom/wildcard/driver.cxx @@ -0,0 +1,185 @@ +// file : examples/cxx/hybrid/custom/wildcard/driver.cxx +// author : Boris Kolpackov +// copyright : not copyrighted - public domain + +#include // memcpy +#include // std::auto_ptr +#include + +#include "email.hxx" + +#include "email-pimpl.hxx" +#include "email-simpl.hxx" + +using namespace std; + +// Extended parser and serializer aggregates for the message +// element. They add parser/serializer aggregates for the +// wildcard elements. +// +namespace email +{ + class message_paggr_ex: public message_paggr + { + public: + message_paggr_ex () + { + envelope_p_.text_parser (text_p_.root_parser ()); + envelope_p_.binary_parser (binary_p_.root_parser ()); + } + + public: + text_paggr text_p_; + binary_paggr binary_p_; + }; + + class message_saggr_ex: public message_saggr + { + public: + message_saggr_ex () + { + envelope_s_.text_serializer (text_s_.root_serializer ()); + envelope_s_.binary_serializer (binary_s_.root_serializer ()); + } + + public: + text_saggr text_s_; + binary_saggr binary_s_; + }; +} + +int +main (int argc, char* argv[]) +{ + const char* input; + + if (argc < 2) + { + input = "STDIN"; + cerr << "XML file not specified, reading from STDIN" << endl; + } + else + input = argv[1]; + + try + { + using namespace email; + + // Parse. + // + message_paggr_ex message_p; + + xml_schema::document_pimpl doc_p ( + message_p.root_parser (), + message_p.root_namespace (), + message_p.root_name ()); + + message_p.pre (); + + if (argc < 2) + doc_p.parse (cin); + else + doc_p.parse (argv[1]); + + auto_ptr msg (message_p.post ()); + + // Print what we've got. + // + cerr << "To: " << msg->to () << endl + << "From: " << msg->from () << endl + << "Subject: " << msg->subject () << endl; + + envelope::body_sequence& body_seq (msg->body ()); + + for (envelope::body_iterator i = body_seq.begin (); + i != body_seq.end (); + ++i) + { + body& b = *i; + + switch (b.body_type ()) + { + case body::type_text: + { + cerr << b.text () << endl + << endl; + break; + } + case body::type_binary: + { + const binary& bin = b.binary (); + cerr << "binary: " << bin.name () << " " + << "type: " << bin.mime () << endl + << endl; + break; + } + default: + { + cerr << "unexpected body type" << endl; + break; + } + } + } + + // Create a reply message. + // + auto_ptr reply (new envelope); + reply->to (msg->from ()); + reply->from (msg->to ()); + reply->subject ("Re: " + msg->subject ()); + + // Add a text body. + // + auto_ptr b (new body); + b->text ("Hi!\n\n" + "Indeed nice pictures. Check out mine.\n\n" + "Jane"); + reply->body ().push_back (b.release ()); + + // Add a (fake) image. + // + auto_ptr pic (new binary); + pic->name ("pic.jpg"); + pic->mime ("image/jpeg"); + pic->size (3); + memcpy (pic->data (), "123", 3); + + b = auto_ptr (new body); + b->binary (pic.release ()); + reply->body ().push_back (b.release ()); + + // Serialize. + // + message_saggr_ex message_s; + + xml_schema::document_simpl doc_s ( + message_s.root_serializer (), + message_s.root_namespace (), + message_s.root_name ()); + + doc_s.add_prefix ("lib", "http://www.codesynthesis.com/email"); + doc_s.add_schema ("http://www.codesynthesis.com/email", "email.xsd"); + + message_s.pre (*reply); + doc_s.serialize (cout); + message_s.post (); + } + catch (const xml_schema::parser_exception& e) + { + cerr << input << ":" << e.line () << ":" << e.column () << ": " + << e.text () << endl; + return 1; + } + catch (const xml_schema::serializer_exception& e) + { + cerr << "error: " << e.text () << endl; + return 1; + } + catch (const std::ios_base::failure&) + { + cerr << input << ": unable to open or read/write failure" << endl; + return 1; + } + + return 0; +} diff --git a/examples/cxx/hybrid/custom/wildcard/email.xml b/examples/cxx/hybrid/custom/wildcard/email.xml new file mode 100644 index 0000000..4385d15 --- /dev/null +++ b/examples/cxx/hybrid/custom/wildcard/email.xml @@ -0,0 +1,31 @@ + + + + + + + Jane Doe <jane@doe.com> + John Doe <john@doe.com> + Surfing pictures + + +Hi Jane, + +Here are cool pictures of me surfing. + +Cheers, +John + + + YmFzZTY0IGJpbmFyeQ== + YmFzZTY0IGJpbmFyeQ== + + diff --git a/examples/cxx/hybrid/custom/wildcard/email.xsd b/examples/cxx/hybrid/custom/wildcard/email.xsd new file mode 100644 index 0000000..310f287 --- /dev/null +++ b/examples/cxx/hybrid/custom/wildcard/email.xsd @@ -0,0 +1,45 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/examples/cxx/hybrid/custom/wildcard/envelope-pimpl.cxx b/examples/cxx/hybrid/custom/wildcard/envelope-pimpl.cxx new file mode 100644 index 0000000..eee573f --- /dev/null +++ b/examples/cxx/hybrid/custom/wildcard/envelope-pimpl.cxx @@ -0,0 +1,100 @@ +// file : examples/cxx/hybrid/custom/wildcard/envelope-pimpl.cxx +// author : Boris Kolpackov +// copyright : not copyrighted - public domain + +#include // std::auto_ptr + +#include "body.hxx" + +// Include email-pimpl.hxx (which includes envelope-pimpl.hxx) +// instead of envelope-pimpl.hxx. +// +#include "email-pimpl.hxx" + +namespace email +{ + void envelope_pimpl:: +#ifndef XSDE_POLYMORPHIC + _start_any_element (const xml_schema::ro_string& ns, + const xml_schema::ro_string& name) +#else + _start_any_element (const xml_schema::ro_string& ns, + const xml_schema::ro_string& name, + const char*) +#endif + { + // We use the depth_ counter to filter out nested elements + // and attributes for the content matched by the wildcard + // but which we don't know how to handle. + // + if (depth_++ == 0) + { + // Top-level (relative to this type) element matched by the + // any wildcard. + // + xml_schema::parser_base* p = 0; + + if (ns == "http://www.codesynthesis.com/email") + { + if (name == "text") + p = text_p_; + else if (name == "binary") + p = binary_p_; + + if (p != 0) + { + // If you are not using exceptions then you will need to add + // error propagation code. For more information on how to do + // this see the wildcard example for the C++/Parser mapping + // (examples/parser/ directory). + // + xml_schema::parser_context& ctx = _context (); + p->pre (); + p->_pre_impl (ctx); + } + } + } + } + + void envelope_pimpl:: + _end_any_element (const xml_schema::ro_string& ns, + const xml_schema::ro_string& name) + { + if (--depth_ == 0) + { + if (ns == "http://www.codesynthesis.com/email") + { + // Note that we don't call _post_impl() (corresponding to + // _pre_impl()) here. It is called automatically by the + // infrastructure. + // + envelope* env = envelope_base_pimpl_state_.envelope_; + + if (name == "text") + { + std::auto_ptr b (new body); + b->text (text_p_->post_string ()); + env->body ().push_back (b.release ()); + } + else if (name == "binary") + { + std::auto_ptr b (new body); + b->binary (binary_p_->post_binary ()); + env->body ().push_back (b.release ()); + } + } + } + } + + void envelope_pimpl:: + _reset () + { + // Note that we always need to call _reset() from the base. + // + envelope_base_pimpl::_reset (); + + depth_ = 0; + text_p_->_reset (); + binary_p_->_reset (); + } +} diff --git a/examples/cxx/hybrid/custom/wildcard/envelope-pimpl.hxx b/examples/cxx/hybrid/custom/wildcard/envelope-pimpl.hxx new file mode 100644 index 0000000..5443ee1 --- /dev/null +++ b/examples/cxx/hybrid/custom/wildcard/envelope-pimpl.hxx @@ -0,0 +1,78 @@ +// file : examples/cxx/hybrid/custom/wildcard/envelope-pimpl.hxx +// author : Boris Kolpackov +// copyright : not copyrighted - public domain + +#ifndef ENVELOPE_PIMPL_HXX +#define ENVELOPE_PIMPL_HXX + +namespace email +{ + // Customized envelope parser implementation. All wildcard events are + // routed to the _start_any_element, _end_any_element, _any_attribute, + // and _any_characters functions. We can dynamically select a parser + // from the _start_any_element after which all inner content will be + // automatically routed to this parser. At the end we will get a call + // to _end_any_element in which we can call post() and save the data. + // + class envelope_pimpl: public envelope_base_pimpl + { + public: + envelope_pimpl () + : depth_ (0), text_p_ (0), binary_p_ (0) + { + } + + // Additional parsers for the wildcard content. + // + void + text_parser (xml_schema::string_pskel& p) + { + text_p_ = &p; + } + + void + binary_parser (binary_pskel& p) + { + binary_p_ = &p; + } + + public: + // If the XSD runtime library was configured with polymorphism + // support, then _start_any_element has a third argument which + // is a dynamic type id that comes from xsi:type or substitution + // groups. + // +#ifndef XSDE_POLYMORPHIC + virtual void + _start_any_element (const xml_schema::ro_string& ns, + const xml_schema::ro_string& name); +#else + virtual void + _start_any_element (const xml_schema::ro_string& ns, + const xml_schema::ro_string& name, + const char*); +#endif + + virtual void + _end_any_element (const xml_schema::ro_string& ns, + const xml_schema::ro_string& name); + + // If we need to be able to reset and reuse the parser after + // an error then we also need to override _reset() and reset + // the parsers that are used to handle wildcards. + // + virtual void + _reset (); + + private: + std::size_t depth_; + + // Parsers for the text and binary elements. + // + private: + xml_schema::string_pskel* text_p_; + binary_pskel* binary_p_; + }; +} + +#endif // ENVELOPE_PIMPL_HXX diff --git a/examples/cxx/hybrid/custom/wildcard/envelope-simpl.cxx b/examples/cxx/hybrid/custom/wildcard/envelope-simpl.cxx new file mode 100644 index 0000000..b6d9f89 --- /dev/null +++ b/examples/cxx/hybrid/custom/wildcard/envelope-simpl.cxx @@ -0,0 +1,137 @@ +// file : examples/cxx/hybrid/custom/wildcard/envelope-simpl.cxx +// author : Boris Kolpackov +// copyright : not copyrighted - public domain + +#include "body.hxx" + +// Include email-simpl.hxx (which includes envelope-simpl.hxx) +// instead of envelope-simpl.hxx. +// +#include "email-simpl.hxx" + +namespace email +{ + void envelope_simpl:: + _pre () + { + // Initialize the body iterator. + // + i_ = envelope_base_simpl_state_.envelope_->body ().begin (); + } + + bool envelope_simpl:: + any_next () + { + envelope::body_const_iterator end ( + envelope_base_simpl_state_.envelope_->body ().end ()); + + // See if there is a body that we know how to serialize. + // + for (; i_ != end; ++i_) + { + body::type t = i_->body_type (); + + if (t == body::type_text || t == body::type_binary) + break; + } + + return i_ != end; + } + + void envelope_simpl:: + any (std::string& ns, std::string& name) + { + ns = "http://www.codesynthesis.com/email"; + + switch (i_->body_type ()) + { + case body::type_text: + { + name = "text"; + break; + } + case body::type_binary: + { + name = "binary"; + break; + } + default: + break; + } + } + + void envelope_simpl:: + serialize_any () + { + xml_schema::serializer_base* s = 0; + const body& b = *i_++; + + // If you are not using exceptions then you will need to add + // error propagation code. For more information on how to do + // this see the wildcard example for the C++/Parser mapping + // (examples/parser/ directory). + // + switch (b.body_type ()) + { + case body::type_text: + { + text_s_->pre (b.text ()); + s = text_s_; + break; + } + case body::type_binary: + { + binary_s_->pre (b.binary ()); + s = binary_s_; + break; + } + default: + break; + } + + if (s != 0) + { + // If XML Schema validation is enabled then we need to check + // for error conditions. + // + xml_schema::serializer_context& ctx = _context (); + + s->_pre_impl (ctx); + +#ifdef XSDE_SERIALIZER_VALIDATION + if (ctx.error_type ()) + return; +#endif + s->_serialize_attributes (); + +#ifdef XSDE_SERIALIZER_VALIDATION + if (ctx.error_type ()) + return; +#endif + s->_serialize_content (); + +#ifdef XSDE_SERIALIZER_VALIDATION + if (ctx.error_type ()) + return; +#endif + s->_post_impl (); + +#ifdef XSDE_SERIALIZER_VALIDATION + if (ctx.error_type ()) + return; +#endif + s->post (); + } + } + + void envelope_simpl:: + _reset () + { + text_s_->_reset (); + binary_s_->_reset (); + + // Note that we always need to call _reset() from the base. + // + envelope_base_simpl::_reset (); + } +} diff --git a/examples/cxx/hybrid/custom/wildcard/envelope-simpl.hxx b/examples/cxx/hybrid/custom/wildcard/envelope-simpl.hxx new file mode 100644 index 0000000..bb2f546 --- /dev/null +++ b/examples/cxx/hybrid/custom/wildcard/envelope-simpl.hxx @@ -0,0 +1,67 @@ +// file : examples/cxx/hybrid/custom/wildcard/envelope-simpl.hxx +// author : Boris Kolpackov +// copyright : not copyrighted - public domain + +#ifndef ENVELOPE_SIMPL_HXX +#define ENVELOPE_SIMPL_HXX + +namespace email +{ + // Customized envelope serializer implementation. Here we implement + // the any_next, any, and serialize_any callbacks to serialize the + // wildcard content. + // + class envelope_simpl: public envelope_base_simpl + { + public: + envelope_simpl () + : text_s_ (0), binary_s_ (0) + { + } + + // Additional serializers for the wildcard content. + // + void + text_serializer (xml_schema::string_sskel& s) + { + text_s_ = &s; + } + + void + binary_serializer (binary_sskel& s) + { + binary_s_ = &s; + } + + public: + virtual void + _pre (); + + virtual bool + any_next (); + + virtual void + any (std::string& ns, std::string& name); + + virtual void + serialize_any (); + + // 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. + // + virtual void + _reset (); + + private: + envelope::body_const_iterator i_; + + // Serializers for the text and binary elements. + // + private: + xml_schema::string_sskel* text_s_; + binary_sskel* binary_s_; + }; +} + +#endif // ENVELOPE_SIMPL_HXX diff --git a/examples/cxx/hybrid/custom/wildcard/envelope.cxx b/examples/cxx/hybrid/custom/wildcard/envelope.cxx new file mode 100644 index 0000000..bec57a3 --- /dev/null +++ b/examples/cxx/hybrid/custom/wildcard/envelope.cxx @@ -0,0 +1,11 @@ +// file : examples/cxx/hybrid/custom/wildcard/envelope.cxx +// author : Boris Kolpackov +// copyright : not copyrighted - public domain + +// Include email.hxx (which includes envelope.hxx) instead of envelope.hxx. +// +#include "email.hxx" + +namespace email +{ +} diff --git a/examples/cxx/hybrid/custom/wildcard/envelope.hxx b/examples/cxx/hybrid/custom/wildcard/envelope.hxx new file mode 100644 index 0000000..56abedd --- /dev/null +++ b/examples/cxx/hybrid/custom/wildcard/envelope.hxx @@ -0,0 +1,39 @@ +// file : examples/cxx/hybrid/custom/wildcard/envelope.hxx +// author : Boris Kolpackov +// copyright : not copyrighted - public domain + +#ifndef ENVELOPE_HXX +#define ENVELOPE_HXX + +namespace email +{ + // Customized envelope type. It adds a sequence of body objects + // to the generated version. + // + class body; + + class envelope: public envelope_base + { + public: + typedef xml_schema::var_seq body_sequence; + typedef body_sequence::iterator body_iterator; + typedef body_sequence::const_iterator body_const_iterator; + + const body_sequence& + body () const + { + return body_; + } + + body_sequence& + body () + { + return body_; + } + + private: + body_sequence body_; + }; +} + +#endif // ENVELOPE_HXX diff --git a/examples/cxx/hybrid/custom/wildcard/makefile b/examples/cxx/hybrid/custom/wildcard/makefile new file mode 100644 index 0000000..dd32b82 --- /dev/null +++ b/examples/cxx/hybrid/custom/wildcard/makefile @@ -0,0 +1,124 @@ +# file : examples/cxx/hybrid/custom/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 body.cxx envelope-pimpl.cxx envelope-simpl.cxx + +obj := $(addprefix $(out_base)/,\ +$(cxx:.cxx=.o) \ +$(xsd:.xsd=.o) \ +$(xsd:.xsd=-pskel.o) \ +$(xsd:.xsd=-pimpl.o) \ +$(xsd:.xsd=-sskel.o) \ +$(xsd:.xsd=-simpl.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 +dist := $(out_base)/.dist +dist-win := $(out_base)/.dist-win +clean := $(out_base)/.clean + +# Build. +# +$(driver): $(obj) $(xsde.l) + +$(obj) $(dep): $(xsde.l.cpp-options) + +genf := $(xsd:.xsd=.hxx) $(xsd:.xsd=.cxx) \ + $(xsd:.xsd=-pskel.hxx) $(xsd:.xsd=-pskel.cxx) \ + $(xsd:.xsd=-pimpl.hxx) $(xsd:.xsd=-pimpl.cxx) \ + $(xsd:.xsd=-sskel.hxx) $(xsd:.xsd=-sskel.cxx) \ + $(xsd:.xsd=-simpl.hxx) $(xsd:.xsd=-simpl.cxx) + +gen := $(addprefix $(out_base)/,$(genf)) + +$(gen): $(out_root)/xsde/xsde +$(gen): xsde := $(out_root)/xsde/xsde +$(gen): xsde_options += --generate-parser --generate-serializer \ +--generate-aggregate --root-element-all \ +--custom-type envelope=v//envelope_base/envelope.hxx \ +--custom-parser envelope=envelope_base_pimpl/envelope-pimpl.hxx \ +--custom-serializer envelope=envelope_base_simpl/envelope-simpl.hxx \ +--hxx-epilogue '\\\#include "body.hxx"' + +$(call include-dep,$(dep)) + +# Convenience alias for default target. +# +.PHONY: $(out_base)/ +$(out_base)/: $(driver) + + +# Dist. +# +dist-common := $(out_base)/.dist-common + +.PHONY: $(dist) $(dist-win) $(dist-common) + +$(dist) $(dist-win) $(dist-common): path := $(subst $(src_root)/,,$(src_base)) + +$(dist-common): + $(call install-data,$(src_base)/driver.cxx,$(dist_prefix)/$(path)/driver.cxx) + $(call install-data,$(src_base)/body.hxx,$(dist_prefix)/$(path)/body.hxx) + $(call install-data,$(src_base)/body.cxx,$(dist_prefix)/$(path)/body.cxx) + $(call install-data,$(src_base)/envelope.hxx,$(dist_prefix)/$(path)/envelope.hxx) + $(call install-data,$(src_base)/envelope.cxx,$(dist_prefix)/$(path)/envelope.cxx) + $(call install-data,$(src_base)/envelope-pimpl.hxx,$(dist_prefix)/$(path)/envelope-pimpl.hxx) + $(call install-data,$(src_base)/envelope-pimpl.cxx,$(dist_prefix)/$(path)/envelope-pimpl.cxx) + $(call install-data,$(src_base)/envelope-simpl.hxx,$(dist_prefix)/$(path)/envelope-simpl.hxx) + $(call install-data,$(src_base)/envelope-simpl.cxx,$(dist_prefix)/$(path)/envelope-simpl.cxx) + $(call install-data,$(src_base)/email.xsd,$(dist_prefix)/$(path)/email.xsd) + $(call install-data,$(src_base)/email.xml,$(dist_prefix)/$(path)/email.xml) + +$(dist): $(dist-common) + $(call install-data,$(src_base)/README,$(dist_prefix)/$(path)/README) + +$(dist-win): $(dist-common) + $(call install-data,$(src_base)/README,$(dist_prefix)/$(path)/README.txt) + $(call message,,unix2dos $(dist_prefix)/$(path)/README.txt) + + +# Clean. +# +.PHONY: $(clean) + +$(clean): $(driver).o.clean \ + $(addsuffix .cxx.clean,$(obj)) \ + $(addsuffix .cxx.clean,$(dep)) \ + $(addprefix $(out_base)/,$(xsd:.xsd=.cxx.xsd.clean)) + + +# Generated .gitignore. +# +ifeq ($(out_base),$(src_base)) +$(gen): | $(out_base)/.gitignore +$(driver): | $(out_base)/.gitignore + +$(out_base)/.gitignore: files := driver $(genf) +$(clean): $(out_base)/.gitignore.clean + +$(call include,$(bld_root)/git/gitignore.make) +endif + + +# 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,$(bld_root)/install.make) +$(call include,$(scf_root)/xsde/hybrid/xsd-cxx.make) + + +# Dependencies. +# +$(call import,$(src_root)/xsde/makefile) +$(call import,$(src_root)/libxsde/xsde/makefile) diff --git a/examples/cxx/hybrid/makefile b/examples/cxx/hybrid/makefile index 06a0ffa..2ee1d25 100644 --- a/examples/cxx/hybrid/makefile +++ b/examples/cxx/hybrid/makefile @@ -5,8 +5,8 @@ include $(dir $(lastword $(MAKEFILE_LIST)))../../../build/bootstrap.make -all_examples := binary compositors hello multiroot streaming library \ -wildcard filter minimal +all_examples := binary compositors custom hello multiroot streaming \ +library wildcard filter minimal build_examples := binary compositors diff --git a/examples/cxx/hybrid/wildcard/README b/examples/cxx/hybrid/wildcard/README index d54b081..e185492 100644 --- a/examples/cxx/hybrid/wildcard/README +++ b/examples/cxx/hybrid/wildcard/README @@ -2,11 +2,14 @@ This example shows how to parse, store in the object model, and serialize XML data matched by XML Schema wildcards (any and anyAttribute) using the Embedded C++/Hybrid mapping. -This example uses the object model as well as parser and serializer -customization mechanisms provided by the C++/Hybrid mapping. For more -information, see Section 4.8, "Customizing the Object Model" and Section -6.1, "Customizing Parsers and Serializers" in the Embedded C++/Hybrid -Mapping Getting Started Guide. +This example uses the custom data mechanism to store the wildcard data +in the object model as well as parser and serializer customization to +parse and serialize the wildcard data. For more information, see Section +4.8, "Customizing the Object Model" and Section 6.1, "Customizing Parsers +and Serializers" in the Embedded C++/Hybrid Mapping Getting Started Guide. + +The 'wildcard' example in the examples/cxx/hybrid/custom/ directory shows +how to do the same but using type customization instead of custom data. The example consists of the following files: diff --git a/examples/cxx/hybrid/wildcard/envelope-pimpl.hxx b/examples/cxx/hybrid/wildcard/envelope-pimpl.hxx index 06eb26c..d783cc9 100644 --- a/examples/cxx/hybrid/wildcard/envelope-pimpl.hxx +++ b/examples/cxx/hybrid/wildcard/envelope-pimpl.hxx @@ -12,7 +12,7 @@ namespace email // and _any_characters functions. We can dynamically select a parser // from the _start_any_element after which all inner content will be // automatically routed to this parser. At the end we will get a call - // to _end_any_element in which we can call post(), and save the data. + // to _end_any_element in which we can call post() and save the data. // class envelope_pimpl: public envelope_base_pimpl { -- cgit v1.1