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/hybrid/README | 37 ++ examples/cxx/hybrid/compositors/README | 28 ++ examples/cxx/hybrid/compositors/compositors.xsd | 44 +++ examples/cxx/hybrid/compositors/driver.cxx | 89 +++++ examples/cxx/hybrid/compositors/makefile | 62 ++++ examples/cxx/hybrid/filter/README | 71 ++++ examples/cxx/hybrid/filter/driver.cxx | 98 +++++ examples/cxx/hybrid/filter/makefile | 80 ++++ examples/cxx/hybrid/filter/people-custom-pimpl.cxx | 26 ++ examples/cxx/hybrid/filter/people-custom-pimpl.hxx | 24 ++ examples/cxx/hybrid/filter/people-custom-simpl.cxx | 32 ++ examples/cxx/hybrid/filter/people-custom-simpl.hxx | 23 ++ examples/cxx/hybrid/filter/people.xml | 35 ++ examples/cxx/hybrid/filter/people.xsd | 37 ++ examples/cxx/hybrid/hello/README | 37 ++ examples/cxx/hybrid/hello/driver.cxx | 66 ++++ examples/cxx/hybrid/hello/hello.xml | 20 + examples/cxx/hybrid/hello/hello.xsd | 22 ++ examples/cxx/hybrid/hello/makefile | 71 ++++ examples/cxx/hybrid/library/README | 45 +++ examples/cxx/hybrid/library/driver.cxx | 159 ++++++++ examples/cxx/hybrid/library/library.xml | 53 +++ examples/cxx/hybrid/library/library.xsd | 69 ++++ examples/cxx/hybrid/library/makefile | 78 ++++ examples/cxx/hybrid/makefile | 36 ++ examples/cxx/hybrid/minimal/README | 46 +++ examples/cxx/hybrid/minimal/driver.cxx | 265 +++++++++++++ examples/cxx/hybrid/minimal/makefile | 78 ++++ examples/cxx/hybrid/minimal/people.xml | 28 ++ examples/cxx/hybrid/minimal/people.xsd | 37 ++ examples/cxx/hybrid/multiroot/README | 48 +++ examples/cxx/hybrid/multiroot/balance.xml | 17 + examples/cxx/hybrid/multiroot/deposit.xml | 18 + examples/cxx/hybrid/multiroot/driver.cxx | 224 +++++++++++ examples/cxx/hybrid/multiroot/makefile | 72 ++++ examples/cxx/hybrid/multiroot/protocol.xsd | 51 +++ examples/cxx/hybrid/multiroot/withdraw.xml | 18 + examples/cxx/hybrid/streaming/README | 71 ++++ examples/cxx/hybrid/streaming/driver.cxx | 83 +++++ examples/cxx/hybrid/streaming/makefile | 79 ++++ examples/cxx/hybrid/streaming/object-pimpl.cxx | 47 +++ examples/cxx/hybrid/streaming/object-pimpl.hxx | 33 ++ examples/cxx/hybrid/streaming/object-simpl.cxx | 69 ++++ examples/cxx/hybrid/streaming/object-simpl.hxx | 32 ++ examples/cxx/hybrid/streaming/position.xml | 22 ++ examples/cxx/hybrid/streaming/position.xsd | 28 ++ examples/cxx/hybrid/wildcard/README | 76 ++++ examples/cxx/hybrid/wildcard/body.cxx | 26 ++ examples/cxx/hybrid/wildcard/body.hxx | 81 ++++ examples/cxx/hybrid/wildcard/driver.cxx | 188 ++++++++++ examples/cxx/hybrid/wildcard/email.xml | 31 ++ examples/cxx/hybrid/wildcard/email.xsd | 45 +++ examples/cxx/hybrid/wildcard/envelope-pimpl.cxx | 111 ++++++ examples/cxx/hybrid/wildcard/envelope-pimpl.hxx | 81 ++++ examples/cxx/hybrid/wildcard/envelope-simpl.cxx | 137 +++++++ examples/cxx/hybrid/wildcard/envelope-simpl.hxx | 67 ++++ examples/cxx/hybrid/wildcard/makefile | 80 ++++ examples/cxx/makefile | 20 + examples/cxx/parser/README | 32 ++ examples/cxx/parser/generated/README | 36 ++ examples/cxx/parser/generated/library.xml | 53 +++ examples/cxx/parser/generated/library.xsd | 79 ++++ examples/cxx/parser/generated/makefile | 71 ++++ examples/cxx/parser/hello/README | 33 ++ examples/cxx/parser/hello/driver.cxx | 82 +++++ examples/cxx/parser/hello/hello.xml | 20 + examples/cxx/parser/hello/hello.xsd | 22 ++ examples/cxx/parser/hello/makefile | 64 ++++ examples/cxx/parser/library/README | 53 +++ examples/cxx/parser/library/driver.cxx | 131 +++++++ .../cxx/parser/library/library-pimpl-mixin.cxx | 184 +++++++++ .../cxx/parser/library/library-pimpl-mixin.hxx | 136 +++++++ .../cxx/parser/library/library-pimpl-tiein.cxx | 208 +++++++++++ .../cxx/parser/library/library-pimpl-tiein.hxx | 152 ++++++++ examples/cxx/parser/library/library.hxx | 242 ++++++++++++ examples/cxx/parser/library/library.map | 16 + examples/cxx/parser/library/library.xml | 53 +++ examples/cxx/parser/library/library.xsd | 79 ++++ examples/cxx/parser/library/makefile | 72 ++++ examples/cxx/parser/makefile | 53 +++ examples/cxx/parser/minimal/README | 51 +++ examples/cxx/parser/minimal/driver.cxx | 145 ++++++++ examples/cxx/parser/minimal/gender.hxx | 14 + examples/cxx/parser/minimal/makefile | 66 ++++ examples/cxx/parser/minimal/people-pimpl-mixin.hxx | 82 +++++ examples/cxx/parser/minimal/people-pimpl-tiein.hxx | 90 +++++ examples/cxx/parser/minimal/people.map | 7 + examples/cxx/parser/minimal/people.xml | 28 ++ examples/cxx/parser/minimal/people.xsd | 37 ++ examples/cxx/parser/mixed/README | 54 +++ examples/cxx/parser/mixed/anchor.hxx | 34 ++ examples/cxx/parser/mixed/driver.cxx | 123 +++++++ examples/cxx/parser/mixed/makefile | 66 ++++ examples/cxx/parser/mixed/text.map | 7 + examples/cxx/parser/mixed/text.xml | 18 + examples/cxx/parser/mixed/text.xsd | 29 ++ examples/cxx/parser/multiroot/README | 61 +++ examples/cxx/parser/multiroot/balance.xml | 17 + examples/cxx/parser/multiroot/deposit.xml | 18 + examples/cxx/parser/multiroot/driver.cxx | 245 ++++++++++++ examples/cxx/parser/multiroot/makefile | 71 ++++ .../cxx/parser/multiroot/protocol-pimpl-mixin.cxx | 47 +++ .../cxx/parser/multiroot/protocol-pimpl-mixin.hxx | 49 +++ .../cxx/parser/multiroot/protocol-pimpl-tiein.cxx | 59 +++ .../cxx/parser/multiroot/protocol-pimpl-tiein.hxx | 55 +++ examples/cxx/parser/multiroot/protocol.hxx | 62 ++++ examples/cxx/parser/multiroot/protocol.map | 12 + examples/cxx/parser/multiroot/protocol.xsd | 51 +++ examples/cxx/parser/multiroot/withdraw.xml | 18 + examples/cxx/parser/polymorphism/README | 38 ++ examples/cxx/parser/polymorphism/driver.cxx | 115 ++++++ examples/cxx/parser/polymorphism/makefile | 71 ++++ .../parser/polymorphism/supermen-pimpl-mixin.cxx | 86 +++++ .../parser/polymorphism/supermen-pimpl-mixin.hxx | 69 ++++ .../parser/polymorphism/supermen-pimpl-tiein.cxx | 104 ++++++ .../parser/polymorphism/supermen-pimpl-tiein.hxx | 81 ++++ examples/cxx/parser/polymorphism/supermen.xml | 26 ++ examples/cxx/parser/polymorphism/supermen.xsd | 49 +++ examples/cxx/parser/polyroot/README | 47 +++ examples/cxx/parser/polyroot/batman.xml | 17 + examples/cxx/parser/polyroot/driver.cxx | 216 +++++++++++ examples/cxx/parser/polyroot/makefile | 71 ++++ examples/cxx/parser/polyroot/person.xml | 16 + examples/cxx/parser/polyroot/superman.xml | 17 + .../cxx/parser/polyroot/supermen-pimpl-mixin.cxx | 83 +++++ .../cxx/parser/polyroot/supermen-pimpl-mixin.hxx | 65 ++++ .../cxx/parser/polyroot/supermen-pimpl-tiein.cxx | 101 +++++ .../cxx/parser/polyroot/supermen-pimpl-tiein.hxx | 77 ++++ examples/cxx/parser/polyroot/supermen.xsd | 40 ++ examples/cxx/parser/wildcard/README | 33 ++ examples/cxx/parser/wildcard/driver.cxx | 359 ++++++++++++++++++ examples/cxx/parser/wildcard/email.xml | 32 ++ examples/cxx/parser/wildcard/email.xsd | 51 +++ examples/cxx/parser/wildcard/makefile | 64 ++++ examples/cxx/serializer/README | 20 + examples/cxx/serializer/hello/README | 25 ++ examples/cxx/serializer/hello/driver.cxx | 90 +++++ examples/cxx/serializer/hello/hello.xsd | 22 ++ examples/cxx/serializer/hello/makefile | 64 ++++ examples/cxx/serializer/library/README | 44 +++ examples/cxx/serializer/library/driver.cxx | 140 +++++++ .../cxx/serializer/library/library-simpl-mixin.cxx | 184 +++++++++ .../cxx/serializer/library/library-simpl-mixin.hxx | 138 +++++++ .../cxx/serializer/library/library-simpl-tiein.cxx | 208 +++++++++++ .../cxx/serializer/library/library-simpl-tiein.hxx | 154 ++++++++ examples/cxx/serializer/library/library.hxx | 270 ++++++++++++++ examples/cxx/serializer/library/library.map | 22 ++ examples/cxx/serializer/library/library.xsd | 79 ++++ examples/cxx/serializer/library/makefile | 72 ++++ examples/cxx/serializer/makefile | 49 +++ examples/cxx/serializer/minimal/README | 47 +++ examples/cxx/serializer/minimal/driver.cxx | 139 +++++++ examples/cxx/serializer/minimal/makefile | 66 ++++ .../cxx/serializer/minimal/people-simpl-mixin.hxx | 82 +++++ .../cxx/serializer/minimal/people-simpl-tiein.hxx | 90 +++++ examples/cxx/serializer/minimal/people.hxx | 30 ++ examples/cxx/serializer/minimal/people.map | 9 + examples/cxx/serializer/minimal/people.xsd | 37 ++ examples/cxx/serializer/polymorphism/README | 44 +++ examples/cxx/serializer/polymorphism/driver.cxx | 120 ++++++ examples/cxx/serializer/polymorphism/makefile | 73 ++++ .../polymorphism/supermen-simpl-mixin.cxx | 83 +++++ .../polymorphism/supermen-simpl-mixin.hxx | 51 +++ .../polymorphism/supermen-simpl-tiein.cxx | 108 ++++++ .../polymorphism/supermen-simpl-tiein.hxx | 69 ++++ examples/cxx/serializer/polymorphism/supermen.hxx | 129 +++++++ examples/cxx/serializer/polymorphism/supermen.map | 10 + examples/cxx/serializer/polymorphism/supermen.xsd | 49 +++ examples/cxx/serializer/polyroot/README | 46 +++ examples/cxx/serializer/polyroot/driver.cxx | 142 +++++++ examples/cxx/serializer/polyroot/makefile | 73 ++++ .../serializer/polyroot/supermen-simpl-mixin.cxx | 35 ++ .../serializer/polyroot/supermen-simpl-mixin.hxx | 35 ++ .../serializer/polyroot/supermen-simpl-tiein.cxx | 59 +++ .../serializer/polyroot/supermen-simpl-tiein.hxx | 53 +++ examples/cxx/serializer/polyroot/supermen.hxx | 129 +++++++ examples/cxx/serializer/polyroot/supermen.map | 9 + examples/cxx/serializer/polyroot/supermen.xsd | 41 +++ 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 ++++ 184 files changed, 13275 insertions(+) create mode 100644 examples/cxx/hybrid/README create mode 100644 examples/cxx/hybrid/compositors/README create mode 100644 examples/cxx/hybrid/compositors/compositors.xsd create mode 100644 examples/cxx/hybrid/compositors/driver.cxx create mode 100644 examples/cxx/hybrid/compositors/makefile create mode 100644 examples/cxx/hybrid/filter/README create mode 100644 examples/cxx/hybrid/filter/driver.cxx create mode 100644 examples/cxx/hybrid/filter/makefile create mode 100644 examples/cxx/hybrid/filter/people-custom-pimpl.cxx create mode 100644 examples/cxx/hybrid/filter/people-custom-pimpl.hxx create mode 100644 examples/cxx/hybrid/filter/people-custom-simpl.cxx create mode 100644 examples/cxx/hybrid/filter/people-custom-simpl.hxx create mode 100644 examples/cxx/hybrid/filter/people.xml create mode 100644 examples/cxx/hybrid/filter/people.xsd create mode 100644 examples/cxx/hybrid/hello/README create mode 100644 examples/cxx/hybrid/hello/driver.cxx create mode 100644 examples/cxx/hybrid/hello/hello.xml create mode 100644 examples/cxx/hybrid/hello/hello.xsd create mode 100644 examples/cxx/hybrid/hello/makefile create mode 100644 examples/cxx/hybrid/library/README create mode 100644 examples/cxx/hybrid/library/driver.cxx create mode 100644 examples/cxx/hybrid/library/library.xml create mode 100644 examples/cxx/hybrid/library/library.xsd create mode 100644 examples/cxx/hybrid/library/makefile create mode 100644 examples/cxx/hybrid/makefile create mode 100644 examples/cxx/hybrid/minimal/README create mode 100644 examples/cxx/hybrid/minimal/driver.cxx create mode 100644 examples/cxx/hybrid/minimal/makefile create mode 100644 examples/cxx/hybrid/minimal/people.xml create mode 100644 examples/cxx/hybrid/minimal/people.xsd create mode 100644 examples/cxx/hybrid/multiroot/README create mode 100644 examples/cxx/hybrid/multiroot/balance.xml create mode 100644 examples/cxx/hybrid/multiroot/deposit.xml create mode 100644 examples/cxx/hybrid/multiroot/driver.cxx create mode 100644 examples/cxx/hybrid/multiroot/makefile create mode 100644 examples/cxx/hybrid/multiroot/protocol.xsd create mode 100644 examples/cxx/hybrid/multiroot/withdraw.xml create mode 100644 examples/cxx/hybrid/streaming/README create mode 100644 examples/cxx/hybrid/streaming/driver.cxx create mode 100644 examples/cxx/hybrid/streaming/makefile create mode 100644 examples/cxx/hybrid/streaming/object-pimpl.cxx create mode 100644 examples/cxx/hybrid/streaming/object-pimpl.hxx create mode 100644 examples/cxx/hybrid/streaming/object-simpl.cxx create mode 100644 examples/cxx/hybrid/streaming/object-simpl.hxx create mode 100644 examples/cxx/hybrid/streaming/position.xml create mode 100644 examples/cxx/hybrid/streaming/position.xsd create mode 100644 examples/cxx/hybrid/wildcard/README create mode 100644 examples/cxx/hybrid/wildcard/body.cxx create mode 100644 examples/cxx/hybrid/wildcard/body.hxx create mode 100644 examples/cxx/hybrid/wildcard/driver.cxx create mode 100644 examples/cxx/hybrid/wildcard/email.xml create mode 100644 examples/cxx/hybrid/wildcard/email.xsd create mode 100644 examples/cxx/hybrid/wildcard/envelope-pimpl.cxx create mode 100644 examples/cxx/hybrid/wildcard/envelope-pimpl.hxx create mode 100644 examples/cxx/hybrid/wildcard/envelope-simpl.cxx create mode 100644 examples/cxx/hybrid/wildcard/envelope-simpl.hxx create mode 100644 examples/cxx/hybrid/wildcard/makefile create mode 100644 examples/cxx/makefile create mode 100644 examples/cxx/parser/README create mode 100644 examples/cxx/parser/generated/README create mode 100644 examples/cxx/parser/generated/library.xml create mode 100644 examples/cxx/parser/generated/library.xsd create mode 100644 examples/cxx/parser/generated/makefile create mode 100644 examples/cxx/parser/hello/README create mode 100644 examples/cxx/parser/hello/driver.cxx create mode 100644 examples/cxx/parser/hello/hello.xml create mode 100644 examples/cxx/parser/hello/hello.xsd create mode 100644 examples/cxx/parser/hello/makefile create mode 100644 examples/cxx/parser/library/README create mode 100644 examples/cxx/parser/library/driver.cxx create mode 100644 examples/cxx/parser/library/library-pimpl-mixin.cxx create mode 100644 examples/cxx/parser/library/library-pimpl-mixin.hxx create mode 100644 examples/cxx/parser/library/library-pimpl-tiein.cxx create mode 100644 examples/cxx/parser/library/library-pimpl-tiein.hxx create mode 100644 examples/cxx/parser/library/library.hxx create mode 100644 examples/cxx/parser/library/library.map create mode 100644 examples/cxx/parser/library/library.xml create mode 100644 examples/cxx/parser/library/library.xsd create mode 100644 examples/cxx/parser/library/makefile create mode 100644 examples/cxx/parser/makefile create mode 100644 examples/cxx/parser/minimal/README create mode 100644 examples/cxx/parser/minimal/driver.cxx create mode 100644 examples/cxx/parser/minimal/gender.hxx create mode 100644 examples/cxx/parser/minimal/makefile create mode 100644 examples/cxx/parser/minimal/people-pimpl-mixin.hxx create mode 100644 examples/cxx/parser/minimal/people-pimpl-tiein.hxx create mode 100644 examples/cxx/parser/minimal/people.map create mode 100644 examples/cxx/parser/minimal/people.xml create mode 100644 examples/cxx/parser/minimal/people.xsd create mode 100644 examples/cxx/parser/mixed/README create mode 100644 examples/cxx/parser/mixed/anchor.hxx create mode 100644 examples/cxx/parser/mixed/driver.cxx create mode 100644 examples/cxx/parser/mixed/makefile create mode 100644 examples/cxx/parser/mixed/text.map create mode 100644 examples/cxx/parser/mixed/text.xml create mode 100644 examples/cxx/parser/mixed/text.xsd create mode 100644 examples/cxx/parser/multiroot/README create mode 100644 examples/cxx/parser/multiroot/balance.xml create mode 100644 examples/cxx/parser/multiroot/deposit.xml create mode 100644 examples/cxx/parser/multiroot/driver.cxx create mode 100644 examples/cxx/parser/multiroot/makefile create mode 100644 examples/cxx/parser/multiroot/protocol-pimpl-mixin.cxx create mode 100644 examples/cxx/parser/multiroot/protocol-pimpl-mixin.hxx create mode 100644 examples/cxx/parser/multiroot/protocol-pimpl-tiein.cxx create mode 100644 examples/cxx/parser/multiroot/protocol-pimpl-tiein.hxx create mode 100644 examples/cxx/parser/multiroot/protocol.hxx create mode 100644 examples/cxx/parser/multiroot/protocol.map create mode 100644 examples/cxx/parser/multiroot/protocol.xsd create mode 100644 examples/cxx/parser/multiroot/withdraw.xml create mode 100644 examples/cxx/parser/polymorphism/README create mode 100644 examples/cxx/parser/polymorphism/driver.cxx create mode 100644 examples/cxx/parser/polymorphism/makefile create mode 100644 examples/cxx/parser/polymorphism/supermen-pimpl-mixin.cxx create mode 100644 examples/cxx/parser/polymorphism/supermen-pimpl-mixin.hxx create mode 100644 examples/cxx/parser/polymorphism/supermen-pimpl-tiein.cxx create mode 100644 examples/cxx/parser/polymorphism/supermen-pimpl-tiein.hxx create mode 100644 examples/cxx/parser/polymorphism/supermen.xml create mode 100644 examples/cxx/parser/polymorphism/supermen.xsd create mode 100644 examples/cxx/parser/polyroot/README create mode 100644 examples/cxx/parser/polyroot/batman.xml create mode 100644 examples/cxx/parser/polyroot/driver.cxx create mode 100644 examples/cxx/parser/polyroot/makefile create mode 100644 examples/cxx/parser/polyroot/person.xml create mode 100644 examples/cxx/parser/polyroot/superman.xml create mode 100644 examples/cxx/parser/polyroot/supermen-pimpl-mixin.cxx create mode 100644 examples/cxx/parser/polyroot/supermen-pimpl-mixin.hxx create mode 100644 examples/cxx/parser/polyroot/supermen-pimpl-tiein.cxx create mode 100644 examples/cxx/parser/polyroot/supermen-pimpl-tiein.hxx create mode 100644 examples/cxx/parser/polyroot/supermen.xsd create mode 100644 examples/cxx/parser/wildcard/README create mode 100644 examples/cxx/parser/wildcard/driver.cxx create mode 100644 examples/cxx/parser/wildcard/email.xml create mode 100644 examples/cxx/parser/wildcard/email.xsd create mode 100644 examples/cxx/parser/wildcard/makefile create mode 100644 examples/cxx/serializer/README create mode 100644 examples/cxx/serializer/hello/README create mode 100644 examples/cxx/serializer/hello/driver.cxx create mode 100644 examples/cxx/serializer/hello/hello.xsd create mode 100644 examples/cxx/serializer/hello/makefile create mode 100644 examples/cxx/serializer/library/README create mode 100644 examples/cxx/serializer/library/driver.cxx create mode 100644 examples/cxx/serializer/library/library-simpl-mixin.cxx create mode 100644 examples/cxx/serializer/library/library-simpl-mixin.hxx create mode 100644 examples/cxx/serializer/library/library-simpl-tiein.cxx create mode 100644 examples/cxx/serializer/library/library-simpl-tiein.hxx create mode 100644 examples/cxx/serializer/library/library.hxx create mode 100644 examples/cxx/serializer/library/library.map create mode 100644 examples/cxx/serializer/library/library.xsd create mode 100644 examples/cxx/serializer/library/makefile create mode 100644 examples/cxx/serializer/makefile create mode 100644 examples/cxx/serializer/minimal/README create mode 100644 examples/cxx/serializer/minimal/driver.cxx create mode 100644 examples/cxx/serializer/minimal/makefile create mode 100644 examples/cxx/serializer/minimal/people-simpl-mixin.hxx create mode 100644 examples/cxx/serializer/minimal/people-simpl-tiein.hxx create mode 100644 examples/cxx/serializer/minimal/people.hxx create mode 100644 examples/cxx/serializer/minimal/people.map create mode 100644 examples/cxx/serializer/minimal/people.xsd create mode 100644 examples/cxx/serializer/polymorphism/README create mode 100644 examples/cxx/serializer/polymorphism/driver.cxx create mode 100644 examples/cxx/serializer/polymorphism/makefile create mode 100644 examples/cxx/serializer/polymorphism/supermen-simpl-mixin.cxx create mode 100644 examples/cxx/serializer/polymorphism/supermen-simpl-mixin.hxx create mode 100644 examples/cxx/serializer/polymorphism/supermen-simpl-tiein.cxx create mode 100644 examples/cxx/serializer/polymorphism/supermen-simpl-tiein.hxx create mode 100644 examples/cxx/serializer/polymorphism/supermen.hxx create mode 100644 examples/cxx/serializer/polymorphism/supermen.map create mode 100644 examples/cxx/serializer/polymorphism/supermen.xsd create mode 100644 examples/cxx/serializer/polyroot/README create mode 100644 examples/cxx/serializer/polyroot/driver.cxx create mode 100644 examples/cxx/serializer/polyroot/makefile create mode 100644 examples/cxx/serializer/polyroot/supermen-simpl-mixin.cxx create mode 100644 examples/cxx/serializer/polyroot/supermen-simpl-mixin.hxx create mode 100644 examples/cxx/serializer/polyroot/supermen-simpl-tiein.cxx create mode 100644 examples/cxx/serializer/polyroot/supermen-simpl-tiein.hxx create mode 100644 examples/cxx/serializer/polyroot/supermen.hxx create mode 100644 examples/cxx/serializer/polyroot/supermen.map create mode 100644 examples/cxx/serializer/polyroot/supermen.xsd 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') diff --git a/examples/cxx/hybrid/README b/examples/cxx/hybrid/README new file mode 100644 index 0000000..ee55a90 --- /dev/null +++ b/examples/cxx/hybrid/README @@ -0,0 +1,37 @@ +This directory contains a number of examples that show how to +use the Embedded C++/Hybrid 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 parse XML + documents. + +library + Shows how to handle more complex data structures, modify the + object model, and serialize the modified object model back to + XML. + +minimal + Shows how to perform parsing and serialization as well as use the + object model when the mapping is configured without support for + STL, iostream, or C++ exceptions. + +multiroot + Shows how to parse XML vocabularies with multiple root elements. + +wildcard + Shows how to parse, store in the object model, and serialize XML + data matched by XML Schema wildcards (any and anyAttribute). + +filter + Shows how to filter the XML data during parsing and object model + during serialization. + +streaming + Shows how to perform partially event-driven, partially in-memory + XML processing. + +compositors + Shows how to create, access, and modify object models with complex + nested choice and sequence compositors. diff --git a/examples/cxx/hybrid/compositors/README b/examples/cxx/hybrid/compositors/README new file mode 100644 index 0000000..b02a023 --- /dev/null +++ b/examples/cxx/hybrid/compositors/README @@ -0,0 +1,28 @@ +This example shows how to create, access, and modify object models with +complex nested choice and sequence compositors in the Embedded C++/Hybrid +mapping. + +For more information about nested compositors see Section 4.4, "Compositors" +in the Embedded C++/Hybrid Mapping Getting Started Guide. + + +The example consists of the following files: + +compositors.xsd + XML Schema which defines a number of types with nested compositors. + +compositors.hxx +compositors.cxx + + Object model classes. These are generated by the XSD/e compiler from + compositors.xsd. + +driver.cxx + Driver for the example. It shows how to create, access, and modify object + models that use nested choice and sequence compositors. The driver does + not produce any output. + + +To run the example simply execute: + +$ ./driver diff --git a/examples/cxx/hybrid/compositors/compositors.xsd b/examples/cxx/hybrid/compositors/compositors.xsd new file mode 100644 index 0000000..85f0db7 --- /dev/null +++ b/examples/cxx/hybrid/compositors/compositors.xsd @@ -0,0 +1,44 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/examples/cxx/hybrid/compositors/driver.cxx b/examples/cxx/hybrid/compositors/driver.cxx new file mode 100644 index 0000000..5d7dd01 --- /dev/null +++ b/examples/cxx/hybrid/compositors/driver.cxx @@ -0,0 +1,89 @@ +// file : examples/cxx/hybrid/compositors/driver.cxx +// author : Boris Kolpackov +// copyright : not copyrighted - public domain + +#include "compositors.hxx" + +int +main (int, char*[]) +{ + // Simple choice. + // + simple_choice sc; + + sc.a (123); // Automatically sets arm to a_tag. + + switch (sc.choice_arm ()) + { + case simple_choice::a_tag: + { + sc.a ()++; + break; + } + case simple_choice::b_tag: + { + // The b element is optional so we first need to check + // if it is present. + // + if (sc.b_present ()) + { + sc.b_present (false); + } + + break; + } + case simple_choice::c_tag: + { + // The c element is a sequence. + // + simple_choice::c_sequence& s = sc.c (); + + for (simple_choice::c_iterator i = s.begin (); i != s.end(); ++i) + { + *i = !*i; + } + + break; + } + } + + + // Nested choice. + // + nested_choice nc; + + // Initialize the choice with the 'sequence' arm. + // + nc.choice_present (true); + nested_choice::choice_type& c = nc.choice (); + c.choice_arm (nested_choice::choice_type::sequence_tag); + c.sequence ().b (123); + c.sequence ().c (true); + + nc.d (456); + + + // Nested sequence. + // + nested_sequence ns; + nested_sequence::sequence_sequence& s = ns.sequence (); + + for (int i = 0; i < 10; ++i) + { + nested_sequence::sequence_type x; + x.a (i); + + if (i % 2) + { + // Initialize the nested sequence. + // + x.sequence1_present (true); + x.sequence1 ().b (i); + x.sequence1 ().c (true); + } + + s.push_back (x); + } + + return 0; +} diff --git a/examples/cxx/hybrid/compositors/makefile b/examples/cxx/hybrid/compositors/makefile new file mode 100644 index 0000000..2bab6e1 --- /dev/null +++ b/examples/cxx/hybrid/compositors/makefile @@ -0,0 +1,62 @@ +# file : examples/cxx/hybrid/compositors/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 := compositors.xsd +cxx := driver.cxx + +obj := $(addprefix $(out_base)/,$(cxx:.cxx=.o) $(xsd:.xsd=.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): $(xsde.l.cpp-options) + +gen := $(out_base)/$(xsd:.xsd=.hxx) \ + $(out_base)/$(xsd:.xsd=.cxx) + +$(gen): $(out_root)/xsde/xsde +$(gen): xsde := $(out_root)/xsde/xsde +$(gen): xsde_options += --generate-inline + +$(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=.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/hybrid/xsd-cxx.make) + + +# Dependencies. +# +$(call import,$(src_root)/xsde/makefile) +$(call import,$(src_root)/libxsde/xsde/makefile) diff --git a/examples/cxx/hybrid/filter/README b/examples/cxx/hybrid/filter/README new file mode 100644 index 0000000..6ff8f76 --- /dev/null +++ b/examples/cxx/hybrid/filter/README @@ -0,0 +1,71 @@ +This example shows how to filter the XML data during parsing and object +model during serialization in the Embedded C++/Hybrid mapping. Filtering +allows only parts of the XML document to be parsed into the object model +or only parts of the object model to be serialized to XML. + +This example uses the 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: + +people.xsd + XML Schema which describes a collection of person records. + +people.xml + Sample XML instance document. + +people.hxx +people.cxx + +people-pskel.hxx +people-pskel.cxx +people-pimpl.hxx +people-pimpl.cxx + +people-pskel.hxx +people-pskel.cxx +people-pimpl.hxx +people-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 people.xsd. The + --generate-parser, --generate-serializer, and --generate-aggregate + options were used to request the generation of the parsing and + serialization code. The --custom-parser option was used to customize + the people_pimpl parser implementation. The --custom-serializer + option was used to customize the people_simpl serializer + implementation. + +people-custom-pimpl.hxx +people-custom-pimpl.cxx + Custom people parser implementation. It uses the implementation + generated by the XSD/e compiler as a base and overrides the person() + callback to filter the records being parsed. + +people-custom-simpl.hxx +people-custom-simpl.cxx + Custom people serializer implementation. It uses the implementation + generated by the XSD/e compiler as a base and overrides the + person_next() callbacks to filter the records being serialized. + +driver.cxx + Driver for the example. It first sets the filter parameters on the + parser object and then calls it to construct the object model from + the input XML file. Only records matching the parser filter end up + in the object model. The driver then prints the content of the object + model to STDERR. Finally, the driver sets the filter parameters on + the serializer object and calls it to serialize the object model back + to XML. Only records matching the serializer filter end up in the + resulting XML. + +To run the example on the sample XML instance document simply execute: + +$ ./driver people.xml + +The example reads from STDIN if input file is not specified: + +$ ./driver +// copyright : not copyrighted - public domain + +#include // std::auto_ptr +#include + +#include "people.hxx" + +#include "people-pimpl.hxx" +#include "people-simpl.hxx" + +using namespace std; + +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 + { + // Parse. + // + people_paggr people_p; + people_pimpl& root_p = people_p.root_parser (); + + // Initialize the filter. + // + root_p.age_filter (1, 30); + + xml_schema::document_pimpl doc_p (root_p, people_p.root_name ()); + + people_p.pre (); + + if (argc < 2) + doc_p.parse (cin); + else + doc_p.parse (argv[1]); + + auto_ptr ppl (people_p.post ()); + + // Print what we've got. + // + people::person_sequence& ps = ppl->person (); + + for (people::person_iterator i = ps.begin (); i != ps.end (); ++i) + { + cerr << "first: " << i->first_name () << endl + << "last: " << i->last_name () << endl + << "gender: " << i->gender () << endl + << "age: " << i->age () << endl + << endl; + } + + // Serialize. + // + people_saggr people_s; + people_simpl& root_s = people_s.root_serializer (); + + // Initialize the filter. + // + gender g; + g.assign ("female"); + root_s.gender_filter (g); + + xml_schema::document_simpl doc_s (root_s, people_s.root_name ()); + + people_s.pre (*ppl); + doc_s.serialize (cout); + people_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/filter/makefile b/examples/cxx/hybrid/filter/makefile new file mode 100644 index 0000000..4273a59 --- /dev/null +++ b/examples/cxx/hybrid/filter/makefile @@ -0,0 +1,80 @@ +# file : examples/cxx/hybrid/filter/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 := people.xsd +cxx := driver.cxx people-custom-pimpl.cxx people-custom-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 +clean := $(out_base)/.clean + +# Build. +# +$(driver): $(obj) $(xsde.l) + +$(obj) $(dep): $(xsde.l.cpp-options) + +gen := $(out_base)/$(xsd:.xsd=.hxx) \ + $(out_base)/$(xsd:.xsd=.cxx) \ + $(out_base)/$(xsd:.xsd=-pskel.hxx) \ + $(out_base)/$(xsd:.xsd=-pskel.cxx) \ + $(out_base)/$(xsd:.xsd=-pimpl.hxx) \ + $(out_base)/$(xsd:.xsd=-pimpl.cxx) \ + $(out_base)/$(xsd:.xsd=-sskel.hxx) \ + $(out_base)/$(xsd:.xsd=-sskel.cxx) \ + $(out_base)/$(xsd:.xsd=-simpl.hxx) \ + $(out_base)/$(xsd:.xsd=-simpl.cxx) + +$(gen): $(out_root)/xsde/xsde +$(gen): xsde := $(out_root)/xsde/xsde +$(gen): xsde_options += --generate-parser --generate-serializer \ +--generate-aggregate \ +--custom-parser people=people_base_pimpl/people-custom-pimpl.hxx \ +--custom-serializer people=people_base_simpl/people-custom-simpl.hxx + +$(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=.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/hybrid/xsd-cxx.make) + + +# Dependencies. +# +$(call import,$(src_root)/xsde/makefile) +$(call import,$(src_root)/libxsde/xsde/makefile) diff --git a/examples/cxx/hybrid/filter/people-custom-pimpl.cxx b/examples/cxx/hybrid/filter/people-custom-pimpl.cxx new file mode 100644 index 0000000..e8a096f --- /dev/null +++ b/examples/cxx/hybrid/filter/people-custom-pimpl.cxx @@ -0,0 +1,26 @@ +// file : examples/cxx/hybrid/filter/people-custom-pimpl.cxx +// author : Boris Kolpackov +// copyright : not copyrighted - public domain + +// Include people-pimpl.hxx (which includes people-custom-pimpl.hxx) +// instead of people-custom-pimpl.hxx. +// +#include "people-pimpl.hxx" + +void people_pimpl:: +age_filter (unsigned short min, unsigned short max) +{ + min_age_ = min; + max_age_ = max; +} + +void people_pimpl:: +person (const ::person& p) +{ + // Check if the age constraints are met. + // + unsigned short age = p.age (); + + if (age >= min_age_ && age <= max_age_) + people_base_pimpl::person (p); +} diff --git a/examples/cxx/hybrid/filter/people-custom-pimpl.hxx b/examples/cxx/hybrid/filter/people-custom-pimpl.hxx new file mode 100644 index 0000000..1856811 --- /dev/null +++ b/examples/cxx/hybrid/filter/people-custom-pimpl.hxx @@ -0,0 +1,24 @@ +// file : examples/cxx/hybrid/filter/people-custom-pimpl.hxx +// author : Boris Kolpackov +// copyright : not copyrighted - public domain + +#ifndef PEOPLE_CUSTOM_PIMPL_HXX +#define PEOPLE_CUSTOM_PIMPL_HXX + +// Customized people parser implementation. +// +class people_pimpl: public people_base_pimpl +{ +public: + void + age_filter (unsigned short min, unsigned short max); + + virtual void + person (const ::person&); + +private: + unsigned short min_age_; + unsigned short max_age_; +}; + +#endif // PEOPLE_CUSTOM_PIMPL_HXX diff --git a/examples/cxx/hybrid/filter/people-custom-simpl.cxx b/examples/cxx/hybrid/filter/people-custom-simpl.cxx new file mode 100644 index 0000000..3e7d9ff --- /dev/null +++ b/examples/cxx/hybrid/filter/people-custom-simpl.cxx @@ -0,0 +1,32 @@ +// file : examples/cxx/hybrid/filter/people-custom-simpl.cxx +// author : Boris Kolpackov +// copyright : not copyrighted - public domain + +// Include people-simpl.hxx (which includes people-custom-simpl.hxx) +// instead of people-custom-simpl.hxx. +// +#include "people-simpl.hxx" + +void people_simpl:: +gender_filter (gender g) +{ + gender_ = g; +} + +bool people_simpl:: +person_next () +{ + // See if we have any more person records with the gender we + // are interested in. + // + people::person_const_iterator& i = people_base_simpl_state_.person_; + people::person_const_iterator& e = people_base_simpl_state_.person_end_; + + for (; i != e; ++i) + { + if (i->gender () == gender_) + break; + } + + return i != e; +} diff --git a/examples/cxx/hybrid/filter/people-custom-simpl.hxx b/examples/cxx/hybrid/filter/people-custom-simpl.hxx new file mode 100644 index 0000000..c3df238 --- /dev/null +++ b/examples/cxx/hybrid/filter/people-custom-simpl.hxx @@ -0,0 +1,23 @@ +// file : examples/cxx/hybrid/filter/people-custom-simpl.hxx +// author : Boris Kolpackov +// copyright : not copyrighted - public domain + +#ifndef PEOPLE_CUSTOM_SIMPL_HXX +#define PEOPLE_CUSTOM_SIMPL_HXX + +// Customized people serializer implementation. +// +class people_simpl: public people_base_simpl +{ +public: + void + gender_filter (gender); + + virtual bool + person_next (); + +private: + gender gender_; +}; + +#endif // PEOPLE_CUSTOM_SIMPL_HXX diff --git a/examples/cxx/hybrid/filter/people.xml b/examples/cxx/hybrid/filter/people.xml new file mode 100644 index 0000000..2a3fd11 --- /dev/null +++ b/examples/cxx/hybrid/filter/people.xml @@ -0,0 +1,35 @@ + + + + + + + + John + Doe + male + 32 + + + + Jane + Doe + female + 28 + + + + Joe + Dirt + male + 25 + + + diff --git a/examples/cxx/hybrid/filter/people.xsd b/examples/cxx/hybrid/filter/people.xsd new file mode 100644 index 0000000..bb6e5dd --- /dev/null +++ b/examples/cxx/hybrid/filter/people.xsd @@ -0,0 +1,37 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/examples/cxx/hybrid/hello/README b/examples/cxx/hybrid/hello/README new file mode 100644 index 0000000..dd5a2bb --- /dev/null +++ b/examples/cxx/hybrid/hello/README @@ -0,0 +1,37 @@ +This is a "Hello, world!" example that shows how to use the Embedded +C++/Hybrid mapping to parse XML documents. + +The example consists of the following files: + +hello.xsd + XML Schema which describes "hello" instance documents. + +hello.xml + Sample XML instance document. + +hello.hxx +hello.cxx + +hello-pskel.hxx +hello-pskel.cxx +hello-pimpl.hxx +hello-pimpl.cxx + Object model (the first pair of files), parser skeletons (the + second pair) and parser implementations (the third pair). These + files are generated by the XSD/e compiler from hello.xsd. The + --generate-parser and --generate-aggregate options were used + to request the generation of the parsing code. + +driver.cxx + Driver for the example. It first calls the parser that + constructs the object model from the input XML file. It + then prints the content of the object model to STDERR. + +To run the example on the sample XML instance document simply +execute: + +$ ./driver hello.xml + +The example reads from STDIN if input file is not specified: + +$ ./driver +// copyright : not copyrighted - public domain + +#include + +#include "hello.hxx" +#include "hello-pimpl.hxx" + +using namespace std; + +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 + { + // Parse. + // + hello_paggr hello_p; + + xml_schema::document_pimpl doc_p (hello_p.root_parser (), + hello_p.root_name ()); + hello_p.pre (); + + if (argc < 2) + doc_p.parse (cin); + else + doc_p.parse (argv[1]); + + hello* h = hello_p.post (); + + // Print what we've got. + // + for (hello::name_const_iterator i = h->name ().begin (); + i != h->name ().end (); + ++i) + { + cout << h->greeting () << ", " << *i << "!" << endl; + } + + delete h; + } + catch (const xml_schema::parser_exception& e) + { + cerr << input << ":" << e.line () << ":" << e.column () << ": " + << e.text () << endl; + return 1; + } + catch (const std::ios_base::failure&) + { + cerr << input << ": unable to open or read failure" << endl; + return 1; + } + + return 0; +} diff --git a/examples/cxx/hybrid/hello/hello.xml b/examples/cxx/hybrid/hello/hello.xml new file mode 100644 index 0000000..32e70f1 --- /dev/null +++ b/examples/cxx/hybrid/hello/hello.xml @@ -0,0 +1,20 @@ + + + + + + + Hello + + sun + moon + world + + diff --git a/examples/cxx/hybrid/hello/hello.xsd b/examples/cxx/hybrid/hello/hello.xsd new file mode 100644 index 0000000..66ea021 --- /dev/null +++ b/examples/cxx/hybrid/hello/hello.xsd @@ -0,0 +1,22 @@ + + + + + + + + + + + + + + + + diff --git a/examples/cxx/hybrid/hello/makefile b/examples/cxx/hybrid/hello/makefile new file mode 100644 index 0000000..b347837 --- /dev/null +++ b/examples/cxx/hybrid/hello/makefile @@ -0,0 +1,71 @@ +# file : examples/cxx/hybrid/hello/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 := hello.xsd +cxx := driver.cxx + +obj := $(addprefix $(out_base)/,\ +$(cxx:.cxx=.o) \ +$(xsd:.xsd=.o) \ +$(xsd:.xsd=-pskel.o) \ +$(xsd:.xsd=-pimpl.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): $(xsde.l.cpp-options) + +gen := $(out_base)/$(xsd:.xsd=.hxx) \ + $(out_base)/$(xsd:.xsd=.cxx) \ + $(out_base)/$(xsd:.xsd=-pskel.hxx) \ + $(out_base)/$(xsd:.xsd=-pskel.cxx) \ + $(out_base)/$(xsd:.xsd=-pimpl.hxx) \ + $(out_base)/$(xsd:.xsd=-pimpl.cxx) + +$(gen): $(out_root)/xsde/xsde +$(gen): xsde := $(out_root)/xsde/xsde +$(gen): xsde_options += --generate-parser --generate-aggregate + +$(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=.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/hybrid/xsd-cxx.make) + + +# Dependencies. +# +$(call import,$(src_root)/xsde/makefile) +$(call import,$(src_root)/libxsde/xsde/makefile) diff --git a/examples/cxx/hybrid/library/README b/examples/cxx/hybrid/library/README new file mode 100644 index 0000000..b44c462 --- /dev/null +++ b/examples/cxx/hybrid/library/README @@ -0,0 +1,45 @@ +This example shows how to use the Embedded C++/Hybrid mapping to parse +XML documents into an in-memory object model, modify this object model, +and serialize it back to XML. + +The example consists of the following files: + +library.xsd + XML Schema which describes a library of books. + +library.xml + Sample XML instance document. + +library.hxx +library.cxx + +library-pskel.hxx +library-pskel.cxx +library-pimpl.hxx +library-pimpl.cxx + +library-pskel.hxx +library-pskel.cxx +library-pimpl.hxx +library-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 + library.xsd. The --generate-parser, --generate-serializer, and + --generate-aggregate options were used to request the generation + of the parsing and serialization code. + +driver.cxx + Driver for the example. It first calls the parser that constructs + the object model from the input XML file. It then prints the content + of the object model to STDERR. Finally, the driver modifies the + object model and calls the serializer to serialize it back to XML. + +To run the example on the sample XML instance document simply execute: + +$ ./driver library.xml + +The example reads from STDIN if input file is not specified: + +$ ./driver +// copyright : not copyrighted - public domain + +#include // std::auto_ptr +#include + +#include "library.hxx" + +#include "library-pimpl.hxx" +#include "library-simpl.hxx" + +using namespace std; + +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 library; + + // Parse. + // + catalog_paggr catalog_p; + + xml_schema::document_pimpl doc_p ( + catalog_p.root_parser (), + catalog_p.root_namespace (), + catalog_p.root_name ()); + + catalog_p.pre (); + + if (argc < 2) + doc_p.parse (cin); + else + doc_p.parse (argv[1]); + + auto_ptr c (catalog_p.post ()); + + // Print what we've got. + // + catalog::book_sequence& books (c->book ()); + + for (catalog::book_const_iterator i = books.begin (); + i != books.end (); + ++i) + { + cerr << "ISBN : " << i->isbn () << endl + << "Title : " << i->title () << endl + << "Genre : " << i->genre () << endl; + + for (book::author_const_iterator j = i->author ().begin (); + j != i->author ().end (); + ++j) + { + cerr << "Author : " << j->name () << endl; + + xml_schema::date born (j->born ()); + + cerr << " Born : " + << born.year () << '-' + << born.month () << '-' + << born.day () << endl; + + if (j->died_present ()) + { + xml_schema::date died (j->died ()); + + cerr << " Died : " + << died.year () << '-' + << died.month () << '-' + << died.day () << endl; + } + } + + cerr << "Available : " << i->available () << endl; + } + + // Remove all unavailable books. + // + for (catalog::book_iterator j = books.begin (); j != books.end ();) + { + if (!j->available ()) + j = books.erase (j); + else + ++j; + } + + // Insert a new book. + // + { + auto_ptr b (new book); + b->available (true); + + isbn n; + n.base_value (679776443); + b->isbn (n); + + title t; + t.assign ("Dead Souls"); + b->title (t); + + genre g; + g.assign ("philosophy"); + b->genre (g); + + author a; + a.name ("Nikolai Gogol"); + a.born (xml_schema::date (1809, 3, 31)); + b->author ().push_back (a); + + books.insert (books.begin (), b.release ()); + } + + // Serialize. + // + catalog_saggr catalog_s; + + xml_schema::document_simpl doc_s ( + catalog_s.root_serializer (), + catalog_s.root_namespace (), + catalog_s.root_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 (*c); + doc_s.serialize (cout); + catalog_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/library/library.xml b/examples/cxx/hybrid/library/library.xml new file mode 100644 index 0000000..6c75d3c --- /dev/null +++ b/examples/cxx/hybrid/library/library.xml @@ -0,0 +1,53 @@ + + + + + + + + 0679760806 + The Master and Margarita + fiction + + + Mikhail Bulgakov + 1891-05-15 + 1940-03-10 + + + + + + 0679600841 + War and Peace + history + + + Leo Tolstoy + 1828-09-09 + 1910-11-20 + + + + + + 0679420290 + Crime and Punishment + philosophy + + + Fyodor Dostoevsky + 1821-11-11 + 1881-02-09 + + + + diff --git a/examples/cxx/hybrid/library/library.xsd b/examples/cxx/hybrid/library/library.xsd new file mode 100644 index 0000000..d276894 --- /dev/null +++ b/examples/cxx/hybrid/library/library.xsd @@ -0,0 +1,69 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/examples/cxx/hybrid/library/makefile b/examples/cxx/hybrid/library/makefile new file mode 100644 index 0000000..91f6997 --- /dev/null +++ b/examples/cxx/hybrid/library/makefile @@ -0,0 +1,78 @@ +# file : examples/cxx/hybrid/library/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 := library.xsd +cxx := driver.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 +clean := $(out_base)/.clean + +# Build. +# +$(driver): $(obj) $(xsde.l) + +$(obj) $(dep): $(xsde.l.cpp-options) + +gen := $(out_base)/$(xsd:.xsd=.hxx) \ + $(out_base)/$(xsd:.xsd=.cxx) \ + $(out_base)/$(xsd:.xsd=-pskel.hxx) \ + $(out_base)/$(xsd:.xsd=-pskel.cxx) \ + $(out_base)/$(xsd:.xsd=-pimpl.hxx) \ + $(out_base)/$(xsd:.xsd=-pimpl.cxx) \ + $(out_base)/$(xsd:.xsd=-sskel.hxx) \ + $(out_base)/$(xsd:.xsd=-sskel.cxx) \ + $(out_base)/$(xsd:.xsd=-simpl.hxx) \ + $(out_base)/$(xsd:.xsd=-simpl.cxx) + +$(gen): $(out_root)/xsde/xsde +$(gen): xsde := $(out_root)/xsde/xsde +$(gen): xsde_options += --generate-parser --generate-serializer \ +--generate-aggregate + +$(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=.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/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 new file mode 100644 index 0000000..d3f0729 --- /dev/null +++ b/examples/cxx/hybrid/makefile @@ -0,0 +1,36 @@ +# file : examples/cxx/hybrid/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 + +examples := compositors + +ifeq ($(xsde_iostream),y) +ifeq ($(xsde_exceptions),y) + +examples += hello multiroot streaming + +ifeq ($(xsde_stl),y) +examples += library wildcard filter +endif + +endif +endif + +ifeq ($(xsde_stl),n) +ifeq ($(xsde_exceptions),n) +examples += minimal +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/hybrid/minimal/README b/examples/cxx/hybrid/minimal/README new file mode 100644 index 0000000..bba2467 --- /dev/null +++ b/examples/cxx/hybrid/minimal/README @@ -0,0 +1,46 @@ +This example shows how to perform parsing and serialization as well as +use the object model when the Embedded C++/Hybrid mapping is configured +without support for STL, iostream, or C++ exceptions. + +The example consists of the following files: + +people.xsd + XML Schema which describes a collection of person records. + +people.xml + Sample XML instance document. + +people.hxx +people.cxx + +people-pskel.hxx +people-pskel.cxx +people-pimpl.hxx +people-pimpl.cxx + +people-pskel.hxx +people-pskel.cxx +people-pimpl.hxx +people-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 people.xsd. The + --generate-parser, --generate-serializer, --generate-aggregate, + --no-stl, --no-iostream, and --no-exceptions options were used to + request the generation of the parsing and serialization code as well + as to disable the use of STL, iostream, and C++ exceptions. + +driver.cxx + Driver for the example. It first calls the parser that constructs the + object model from the input XML file. It then prints the content of + the object model to STDERR. Finally, the driver modifies the object + model and calls the serializer to serialize it back to XML. + +To run the example on the sample XML instance document simply execute: + +$ ./driver people.xml + +The example reads from STDIN if input file is not specified: + +$ ./driver +// copyright : not copyrighted - public domain + +#include + +#include "people.hxx" + +#include "people-pimpl.hxx" +#include "people-simpl.hxx" + +using namespace std; + +// eVC++ 4.0 does not like using xml_schema::strdupx; +// +inline char* +strdupx (const char* s) +{ + return xml_schema::strdupx (s); +} + +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 (int argc, char* argv[]) +{ + const char* input; + + if (argc < 2) + { + input = "STDIN"; + fprintf (stderr, "XML file not specified, reading from STDIN\n"); + } + else + input = argv[1]; + + // Open the file or use STDIN. + // + FILE* f = argc > 1 ? fopen (argv[1], "rb") : stdin; + + if (f == 0) + { + fprintf (stderr, "%s: unable to open\n", input); + return 1; + } + + // Parse. + // + using xml_schema::parser_error; + + parser_error pe; + bool io_error = false; + people* ppl = 0; + + do + { + people_paggr people_p; + xml_schema::document_pimpl doc_p (people_p.root_parser (), + people_p.root_name ()); + + if (pe = doc_p._error ()) + break; + + people_p.pre (); + + if (pe = people_p._error ()) + break; + + char buf[4096]; + + do + { + size_t s = fread (buf, 1, sizeof (buf), f); + + if (s != sizeof (buf) && ferror (f)) + { + io_error = true; + break; + } + + doc_p.parse (buf, s, feof (f) != 0); + pe = doc_p._error (); + + } while (!pe && !feof (f)); + + if (io_error || pe) + break; + + ppl = people_p.post (); + + pe = people_p._error (); + + } while (false); + + if (argc > 1) + fclose (f); + + // Handle parsing errors. + // + if (io_error) + { + fprintf (stderr, "%s: read failure\n", input); + return 1; + } + + if (pe) + { + switch (pe.type ()) + { + case parser_error::sys: + { + fprintf (stderr, "%s: %s\n", input, pe.sys_text ()); + break; + } + case parser_error::xml: + { + fprintf (stderr, "%s:%lu:%lu: %s\n", + input, pe.line (), pe.column (), pe.xml_text ()); + break; + } +#ifdef XSDE_PARSER_VALIDATION + case parser_error::schema: + { + fprintf (stderr, "%s:%lu:%lu: %s\n", + input, pe.line (), pe.column (), pe.schema_text ()); + break; + } +#endif + case parser_error::app: + { + fprintf (stderr, "%s:%lu:%lu: application error %d\n", + input, pe.line (), pe.column (), pe.app_code ()); + break; + } + default: + break; + } + + return 1; + } + + // Print what we've got. + // + people::person_sequence& ps = ppl->person (); + + for (people::person_const_iterator i = ps.begin (); i != ps.end (); ++i) + { + printf ("first: %s\n" "last: %s\n" "gender: %s\n" "age: %hu\n\n", + i->first_name (), + i->last_name (), + i->gender ().base_value (), + i->age ()); + } + + // Remove people that are younger than 30. + // + for (people::person_iterator j = ps.begin (); j != ps.end ();) + { + if (j->age () < 30) + j = ps.erase (j); + else + ++j; + } + + // Insert a new person. + // + { + person* p = new person; + p->first_name (strdupx ("Joe")); + p->last_name (strdupx ("Dirt")); + p->age (36); + + gender* g = new gender; + g->base_value (strdupx ("male")); + p->gender (g); + + ps.insert (ps.begin (), p); + } + + // Serialize. + // + using xml_schema::serializer_error; + + serializer_error se; + writer w; + + do + { + people_saggr people_s; + xml_schema::document_simpl doc_s (people_s.root_serializer (), + people_s.root_name ()); + + doc_s.add_no_namespace_schema ("people.xsd"); + + if (se = doc_s._error ()) + break; + + people_s.pre (*ppl); + + if (se = people_s._error ()) + break; + + doc_s.serialize (w); + + if (se = doc_s._error ()) + break; + + people_s.post (); + + se = people_s._error (); + + } while (false); + + delete ppl; + + // Handle serializer errors. + // + if (se) + { + switch (se.type ()) + { + case serializer_error::sys: + { + fprintf (stderr, "error: %s\n", se.sys_text ()); + break; + } + case serializer_error::xml: + { + fprintf (stderr, "error: %s\n", se.xml_text ()); + break; + } +#ifdef XSDE_SERIALIZER_VALIDATION + case serializer_error::schema: + { + fprintf (stderr, "error: %s\n", se.schema_text ()); + break; + } +#endif + case serializer_error::app: + { + fprintf (stderr, "application error: %d\n", se.app_code ()); + break; + } + default: + break; + } + + return 1; + } + + return 0; +} diff --git a/examples/cxx/hybrid/minimal/makefile b/examples/cxx/hybrid/minimal/makefile new file mode 100644 index 0000000..3401af6 --- /dev/null +++ b/examples/cxx/hybrid/minimal/makefile @@ -0,0 +1,78 @@ +# file : examples/cxx/hybrid/minimal/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 := people.xsd +cxx := driver.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 +clean := $(out_base)/.clean + +# Build. +# +$(driver): $(obj) $(xsde.l) + +$(obj) $(dep): $(xsde.l.cpp-options) + +gen := $(out_base)/$(xsd:.xsd=.hxx) \ + $(out_base)/$(xsd:.xsd=.cxx) \ + $(out_base)/$(xsd:.xsd=-pskel.hxx) \ + $(out_base)/$(xsd:.xsd=-pskel.cxx) \ + $(out_base)/$(xsd:.xsd=-pimpl.hxx) \ + $(out_base)/$(xsd:.xsd=-pimpl.cxx) \ + $(out_base)/$(xsd:.xsd=-sskel.hxx) \ + $(out_base)/$(xsd:.xsd=-sskel.cxx) \ + $(out_base)/$(xsd:.xsd=-simpl.hxx) \ + $(out_base)/$(xsd:.xsd=-simpl.cxx) + +$(gen): $(out_root)/xsde/xsde +$(gen): xsde := $(out_root)/xsde/xsde +$(gen): xsde_options += --generate-parser --generate-serializer \ +--generate-aggregate + +$(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=.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/hybrid/xsd-cxx.make) + + +# Dependencies. +# +$(call import,$(src_root)/xsde/makefile) +$(call import,$(src_root)/libxsde/xsde/makefile) diff --git a/examples/cxx/hybrid/minimal/people.xml b/examples/cxx/hybrid/minimal/people.xml new file mode 100644 index 0000000..83f71cf --- /dev/null +++ b/examples/cxx/hybrid/minimal/people.xml @@ -0,0 +1,28 @@ + + + + + + + + John + Doe + male + 32 + + + + Jane + Doe + female + 28 + + + diff --git a/examples/cxx/hybrid/minimal/people.xsd b/examples/cxx/hybrid/minimal/people.xsd new file mode 100644 index 0000000..d5c2995 --- /dev/null +++ b/examples/cxx/hybrid/minimal/people.xsd @@ -0,0 +1,37 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/examples/cxx/hybrid/multiroot/README b/examples/cxx/hybrid/multiroot/README new file mode 100644 index 0000000..3a7cfae --- /dev/null +++ b/examples/cxx/hybrid/multiroot/README @@ -0,0 +1,48 @@ +This example shows how to parse XML vocabularies with multiple root +elements using the Embedded C++/Hybrid mapping. + +The example consists of the following files: + +protocol.xsd + XML Schema which defines a simple bank account protocol with + requests such as withdraw and deposit. + +balance.xml +withdraw.xml +deposit.xml + Sample XML instances for the protocol requests. + +protocol.hxx +protocol.cxx + +protocol-pskel.hxx +protocol-pskel.cxx +protocol-pimpl.hxx +protocol-pimpl.cxx + Object model (the first pair of files), parser skeletons (the + second pair) and parser implementations (the third pair). These + files are generated by the XSD/e compiler from protocol.xsd. The + --generate-parser and --generate-aggregate options were used to + request the generation of the parsing code. + +driver.cxx + Driver for the example. It implements a custom document parser + that determines which request is being parsed and uses the + corresponding parser implementation. The document parser + intentionally does not support the deposit request to show how + to handle unknown documents. The driver first calls the parser + that constructs the object model from the input XML file. It + then prints the content of the object model to STDERR. + +To run the example on the sample XML request documents simply +execute: + +$ ./driver balance.xml +$ ./driver withdraw.xml +$ ./driver deposit.xml + +The example reads from STDIN if input file is not specified: + +$ ./driver + + + + + + 123456789 + + diff --git a/examples/cxx/hybrid/multiroot/deposit.xml b/examples/cxx/hybrid/multiroot/deposit.xml new file mode 100644 index 0000000..6b5ed30 --- /dev/null +++ b/examples/cxx/hybrid/multiroot/deposit.xml @@ -0,0 +1,18 @@ + + + + + + + 123456789 + 1000000 + + diff --git a/examples/cxx/hybrid/multiroot/driver.cxx b/examples/cxx/hybrid/multiroot/driver.cxx new file mode 100644 index 0000000..5611222 --- /dev/null +++ b/examples/cxx/hybrid/multiroot/driver.cxx @@ -0,0 +1,224 @@ +// file : examples/cxx/hybrid/multiroot/driver.cxx +// author : Boris Kolpackov +// copyright : not copyrighted - public domain + +#include + +#include "protocol.hxx" +#include "protocol-pimpl.hxx" + +using namespace std; +using xml_schema::ro_string; + +namespace protocol +{ + // We are going to use our own "type ids" for the request types. + // + enum request_type + { + unknown_type, + balance_type, + withdraw_type + }; + + // Customize the xml_schema::document_pimpl object to handle our protocol + // vocabulary with multiple root elements. + // + class document_pimpl: public xml_schema::document_pimpl + { + public: + document_pimpl () + : result_type_ (unknown_type) + { + } + + request_type + result_type () const + { + return result_type_; + } + + protocol::balance + balance () const + { + return balance_; + } + + protocol::withdraw + withdraw () const + { + return withdraw_; + } + + protected: + // This function is called to obtain the root element type parser. + // If the returned pointed is 0 then the whole document content + // is ignored. Note that the signature of this function varies + // depending on whether the runtime was built with polymorphism + // support. + // + virtual xml_schema::parser_base* +#ifndef XSDE_POLYMORPHIC + start_root_element (const ro_string& ns, + const ro_string& name) +#else + start_root_element (const ro_string& ns, + const ro_string& name, + const char* /* xsi:type */) +#endif + { + if (ns == "http://www.codesynthesis.com/protocol") + { + if (name == balance_p_.root_name ()) + { + balance_p_.pre (); + return &balance_p_.root_parser (); + } + else if (name == "withdraw") + { + balance_p_.pre (); + return &withdraw_p_.root_parser (); + } + + // Ignore unknown request. + // + return 0; + } + else + { + // This document is from the wrong namespace. If the runtime and + // the generated code are built with validation enabled then we + // can set an XML Schema error. Otherwise, we ignore it. + // +#ifdef XSDE_PARSER_VALIDATION + context_.schema_error ( + xml_schema::parser_schema_error::unexpected_element); +#endif + return 0; + } + } + + // This function is called to indicate the completion of document + // parsing. The parser argument contains the pointer returned by + // start_root_element. + // + virtual void + end_root_element (const ro_string& /* ns */, + const ro_string& /* name */, + xml_schema::parser_base* parser) + { + // We could have handled the result directly in this function + // instead of storing it in the result variables. + // + if (parser == &balance_p_.root_parser ()) + { + result_type_ = balance_type; + balance_ = balance_p_.post (); + } + else if (parser == &withdraw_p_.root_parser ()) + { + result_type_ = withdraw_type; + withdraw_ = withdraw_p_.post (); + } + else + result_type_ = unknown_type; + } + + + public: + // 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 root parsers. We can also get smarter here by caching + // the parser that was used last and only reset that. Note + // that you always need to call _reset() from the base. + // + virtual void + reset () + { + xml_schema::document_pimpl::reset (); + + balance_p_.reset (); + withdraw_p_.reset (); + } + + private: + // Result. + // + request_type result_type_; + protocol::balance balance_; + protocol::withdraw withdraw_; + + // Parsers for various root elements. + // + balance_paggr balance_p_; + withdraw_paggr withdraw_p_; + }; +} + +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 protocol; + + // Parse. + // + document_pimpl doc_p; + + // pre() and post() are called as part of the start_root_element() + // and end_root_element() calls. + // + if (argc < 2) + doc_p.parse (std::cin); + else + doc_p.parse (argv[1]); + + // Print what we've got. + // + switch (doc_p.result_type ()) + { + case balance_type: + { + balance b (doc_p.balance ()); + cerr << "balance request for acc# " << b.account () << endl; + break; + } + case withdraw_type: + { + withdraw w (doc_p.withdraw ()); + cerr << "withdrawal request for acc# " << w.account () << ", " + << "amount: " << w.amount () << endl; + break; + } + case unknown_type: + { + cerr << "unknown request" << endl; + break; + } + } + } + catch (const xml_schema::parser_exception& e) + { + cerr << input << ":" << e.line () << ":" << e.column () << ": " + << e.text () << endl; + return 1; + } + catch (const std::ios_base::failure&) + { + cerr << input << ": unable to open or read failure" << endl; + return 1; + } + + return 0; +} diff --git a/examples/cxx/hybrid/multiroot/makefile b/examples/cxx/hybrid/multiroot/makefile new file mode 100644 index 0000000..1426d38 --- /dev/null +++ b/examples/cxx/hybrid/multiroot/makefile @@ -0,0 +1,72 @@ +# file : examples/cxx/hybrid/multiroot/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 := protocol.xsd +cxx := driver.cxx + +obj := $(addprefix $(out_base)/,\ +$(cxx:.cxx=.o) \ +$(xsd:.xsd=.o) \ +$(xsd:.xsd=-pskel.o) \ +$(xsd:.xsd=-pimpl.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): $(xsde.l.cpp-options) + +gen := $(out_base)/$(xsd:.xsd=.hxx) \ + $(out_base)/$(xsd:.xsd=.cxx) \ + $(out_base)/$(xsd:.xsd=-pskel.hxx) \ + $(out_base)/$(xsd:.xsd=-pskel.cxx) \ + $(out_base)/$(xsd:.xsd=-pimpl.hxx) \ + $(out_base)/$(xsd:.xsd=-pimpl.cxx) + +$(gen): $(out_root)/xsde/xsde +$(gen): xsde := $(out_root)/xsde/xsde +$(gen): xsde_options += --generate-parser --generate-aggregate \ +--root-element-all + +$(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=.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/hybrid/xsd-cxx.make) + + +# Dependencies. +# +$(call import,$(src_root)/xsde/makefile) +$(call import,$(src_root)/libxsde/xsde/makefile) diff --git a/examples/cxx/hybrid/multiroot/protocol.xsd b/examples/cxx/hybrid/multiroot/protocol.xsd new file mode 100644 index 0000000..78a275d --- /dev/null +++ b/examples/cxx/hybrid/multiroot/protocol.xsd @@ -0,0 +1,51 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/examples/cxx/hybrid/multiroot/withdraw.xml b/examples/cxx/hybrid/multiroot/withdraw.xml new file mode 100644 index 0000000..36c7d6c --- /dev/null +++ b/examples/cxx/hybrid/multiroot/withdraw.xml @@ -0,0 +1,18 @@ + + + + + + + 123456789 + 1000000 + + diff --git a/examples/cxx/hybrid/streaming/README b/examples/cxx/hybrid/streaming/README new file mode 100644 index 0000000..216c370 --- /dev/null +++ b/examples/cxx/hybrid/streaming/README @@ -0,0 +1,71 @@ +This example shows how to perform partially event-driven, partially in- +memory processing using the Embedded C++/Hybrid mapping. With partially +event-driven parsing and serialization we can process parts of the +document as they become available as well as handle documents that +are too large to fit into memory. + +This example uses the 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: + +position.xsd + XML Schema which describes a simple object position vocabulary. + The position is represented as a potentially large series of + latitude/longitude measurements. + +position.xml + Sample object position document. + +position.hxx +position.cxx + +position-pskel.hxx +position-pskel.cxx +position-pimpl.hxx +position-pimpl.cxx + +position-pskel.hxx +position-pskel.cxx +position-pimpl.hxx +position-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 + position.xsd. The --generate-parser, --generate-serializer, and + --generate-aggregate options were used to request the generation + of the parsing and serialization code. The --custom-parser option + was used to customize the object_pimpl parser implementation. The + --custom-serializer option was used to customize the object_simpl + serializer implementation. + +object-pimpl.hxx +object-pimpl.cxx + Custom object parser implementation. It calculates the average + latitude and longitude values as position measurements become + available. At the end it prints the object position based on + these calculations. + +object-simpl.hxx +object-simpl.cxx + Custom object serializer implementation. It performs a number of + measurements of the object position and serializes them as they + become available. + +driver.cxx + Driver for the example. It first calls the parser that calculates + and prints the object position without constructing the object + model. It then serializes a new set of measurements which are + taken as serialization progresses. + +To run the example on the sample XML instance document simply execute: + +$ ./driver position.xml + +The example reads from STDIN if input file is not specified: + +$ ./driver +// copyright : not copyrighted - public domain + +#include + +#include "position.hxx" + +#include "position-pimpl.hxx" +#include "position-simpl.hxx" + +using namespace std; + +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 + { + // Parse. + // + object_paggr object_p; + + xml_schema::document_pimpl doc_p ( + object_p.root_parser (), + object_p.root_name ()); + + object_p.pre (); + + if (argc < 2) + doc_p.parse (cin); + else + doc_p.parse (argv[1]); + + object_p.post (); // Ignore the NULL return value. + + // Serialize. + // + object_saggr object_s; + + xml_schema::document_simpl doc_s ( + object_s.root_serializer (), + object_s.root_name ()); + + // Create an object instance. Its only purpose is to carry the + // object id. The position measurements will be supplied directly + // by the custom serializer. + // + object obj; + obj.id (456); + + object_s.pre (obj); + doc_s.serialize (cout); + object_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/streaming/makefile b/examples/cxx/hybrid/streaming/makefile new file mode 100644 index 0000000..9fbedb3 --- /dev/null +++ b/examples/cxx/hybrid/streaming/makefile @@ -0,0 +1,79 @@ +# file : examples/cxx/hybrid/streaming/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 := position.xsd +cxx := driver.cxx object-pimpl.cxx object-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 +clean := $(out_base)/.clean + +# Build. +# +$(driver): $(obj) $(xsde.l) + +$(obj) $(dep): $(xsde.l.cpp-options) + +gen := $(out_base)/$(xsd:.xsd=.hxx) \ + $(out_base)/$(xsd:.xsd=.cxx) \ + $(out_base)/$(xsd:.xsd=-pskel.hxx) \ + $(out_base)/$(xsd:.xsd=-pskel.cxx) \ + $(out_base)/$(xsd:.xsd=-pimpl.hxx) \ + $(out_base)/$(xsd:.xsd=-pimpl.cxx) \ + $(out_base)/$(xsd:.xsd=-sskel.hxx) \ + $(out_base)/$(xsd:.xsd=-sskel.cxx) \ + $(out_base)/$(xsd:.xsd=-simpl.hxx) \ + $(out_base)/$(xsd:.xsd=-simpl.cxx) + +$(gen): $(out_root)/xsde/xsde +$(gen): xsde := $(out_root)/xsde/xsde +$(gen): xsde_options += --generate-parser --generate-serializer \ +--generate-aggregate --custom-parser object=/object-pimpl.hxx \ +--custom-serializer object=/object-simpl.hxx + +$(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=.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/hybrid/xsd-cxx.make) + + +# Dependencies. +# +$(call import,$(src_root)/xsde/makefile) +$(call import,$(src_root)/libxsde/xsde/makefile) diff --git a/examples/cxx/hybrid/streaming/object-pimpl.cxx b/examples/cxx/hybrid/streaming/object-pimpl.cxx new file mode 100644 index 0000000..3f45c79 --- /dev/null +++ b/examples/cxx/hybrid/streaming/object-pimpl.cxx @@ -0,0 +1,47 @@ +// file : examples/cxx/hybrid/streaming/object-pimpl.cxx +// author : Boris Kolpackov +// copyright : not copyrighted - public domain + +#include + +// Include position-pimpl.hxx (which includes object-pimpl.hxx) +// instead of object-pimpl.hxx. +// +#include "position-pimpl.hxx" + +using namespace std; + +void object_pimpl:: +pre () +{ + // Initialize the variables. + // + count_ = 0; + avg_lat_ = 0.0; + avg_lon_ = 0.0; +} + +void object_pimpl:: +id (unsigned int id) +{ + id_ = id; +} + +void object_pimpl:: +position (const ::position& p) +{ + count_++; + avg_lat_ += p.lat (); + avg_lon_ += p.lon (); +} + +object* object_pimpl:: +post_object () +{ + avg_lat_ /= count_; + avg_lon_ /= count_; + + cerr << "object " << id_ << ": " << avg_lat_ << " " << avg_lon_ << endl; + + return 0; // We don't construct the object so return NULL. +} diff --git a/examples/cxx/hybrid/streaming/object-pimpl.hxx b/examples/cxx/hybrid/streaming/object-pimpl.hxx new file mode 100644 index 0000000..8d59063 --- /dev/null +++ b/examples/cxx/hybrid/streaming/object-pimpl.hxx @@ -0,0 +1,33 @@ +// file : examples/cxx/hybrid/streaming/object-pimpl.hxx +// author : Boris Kolpackov +// copyright : not copyrighted - public domain + +#ifndef OBJECT_PIMPL_HXX +#define OBJECT_PIMPL_HXX + +// Customized object parser implementation. +// +class object_pimpl: public object_pskel +{ +public: + virtual void + pre (); + + virtual void + id (unsigned int); + + virtual void + position (const ::position&); + + virtual object* + post_object (); + +private: + unsigned int id_; + + unsigned int count_; + float avg_lat_; + float avg_lon_; +}; + +#endif // OBJECT_PIMPL_HXX diff --git a/examples/cxx/hybrid/streaming/object-simpl.cxx b/examples/cxx/hybrid/streaming/object-simpl.cxx new file mode 100644 index 0000000..f23e0d4 --- /dev/null +++ b/examples/cxx/hybrid/streaming/object-simpl.cxx @@ -0,0 +1,69 @@ +// file : examples/cxx/hybrid/streaming/object-simpl.cxx +// author : Boris Kolpackov +// copyright : not copyrighted - public domain + +// Include position-simpl.hxx (which includes object-simpl.hxx) +// instead of object-simpl.hxx. +// +#include "position-simpl.hxx" + +// Position measurement instrument interface. +// +struct measurements +{ + float lat; + float lon; +}; + +measurements test_measurements [8] = +{ + {-33.8569F, 18.5083F}, + {-33.8568F, 18.5083F}, + {-33.8568F, 18.5082F}, + {-33.8570F, 18.5083F}, + {-33.8569F, 18.5084F}, + {-33.8570F, 18.5084F}, + {-33.8570F, 18.5082F}, + {-33.8569F, 18.5082F} +}; + +static void +measure_position (unsigned int n, float& lat, float& lon) +{ + // Call the instrument to measure the position. + // + lat = test_measurements[n].lat; + lon = test_measurements[n].lon; +} + +// Serializer implementation. +// +void object_simpl:: +pre (const object& obj) +{ + // Cache the object id and determine how many position measuremenets + // we need to take. + // + id_ = obj.id (); + count_ = 8; +} + +unsigned int object_simpl:: +id () +{ + return id_; +} + +bool object_simpl:: +position_next () +{ + return count_ > 0; +} + +const position& object_simpl:: +position () +{ + count_--; + measure_position (count_, cur_pos_.lat (), cur_pos_.lon ()); + return cur_pos_; +} diff --git a/examples/cxx/hybrid/streaming/object-simpl.hxx b/examples/cxx/hybrid/streaming/object-simpl.hxx new file mode 100644 index 0000000..6b20399 --- /dev/null +++ b/examples/cxx/hybrid/streaming/object-simpl.hxx @@ -0,0 +1,32 @@ +// file : examples/cxx/hybrid/streaming/object-simpl.hxx +// author : Boris Kolpackov +// copyright : not copyrighted - public domain + +#ifndef OBJECT_SIMPL_HXX +#define OBJECT_SIMPL_HXX + +// Customized object serializer implementation. +// +class object_simpl: public object_sskel +{ +public: + virtual void + pre (const object&); + + virtual unsigned int + id (); + + virtual bool + position_next (); + + virtual const ::position& + position (); + +private: + unsigned int id_; + + unsigned int count_; + ::position cur_pos_; +}; + +#endif // OBJECT_SIMPL_HXX diff --git a/examples/cxx/hybrid/streaming/position.xml b/examples/cxx/hybrid/streaming/position.xml new file mode 100644 index 0000000..0943bb2 --- /dev/null +++ b/examples/cxx/hybrid/streaming/position.xml @@ -0,0 +1,22 @@ + + + + + + + + + + + + + + + + diff --git a/examples/cxx/hybrid/streaming/position.xsd b/examples/cxx/hybrid/streaming/position.xsd new file mode 100644 index 0000000..70b73f2 --- /dev/null +++ b/examples/cxx/hybrid/streaming/position.xsd @@ -0,0 +1,28 @@ + + + + + + + + + + + + + + + + + + + + + + diff --git a/examples/cxx/hybrid/wildcard/README b/examples/cxx/hybrid/wildcard/README new file mode 100644 index 0000000..d54b081 --- /dev/null +++ b/examples/cxx/hybrid/wildcard/README @@ -0,0 +1,76 @@ +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. + +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-data option was + used to request addition of custom data to 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. + +body.hxx +body.cxx + Implementation of the body class. It is used to store the wildcard + data in the custom data sequence in the envelope class. + +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 it as custom data + in the 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 as custom data in + the 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; + } + + void + destroy_body (void* p, size_t) + { + delete static_cast (p); + } +} diff --git a/examples/cxx/hybrid/wildcard/body.hxx b/examples/cxx/hybrid/wildcard/body.hxx new file mode 100644 index 0000000..512a107 --- /dev/null +++ b/examples/cxx/hybrid/wildcard/body.hxx @@ -0,0 +1,81 @@ +// file : examples/cxx/hybrid/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_; + }; + + // Custom data destructor for body. + // + void + destroy_body (void*, size_t); +} + +#endif // BODY_HXX diff --git a/examples/cxx/hybrid/wildcard/driver.cxx b/examples/cxx/hybrid/wildcard/driver.cxx new file mode 100644 index 0000000..eea5bc7 --- /dev/null +++ b/examples/cxx/hybrid/wildcard/driver.cxx @@ -0,0 +1,188 @@ +// file : examples/cxx/hybrid/wildcard/driver.cxx +// author : Boris Kolpackov +// copyright : not copyrighted - public domain + +#include // memcpy +#include // std::auto_ptr +#include + +#include "email.hxx" +#include "body.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::custom_data_sequence& body_seq (msg->custom_data ()); + + for (envelope::custom_data_iterator i = body_seq.begin (); + i != body_seq.end (); + ++i) + { + body* b = static_cast (*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->custom_data ().destructor (&destroy_body); + + 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->custom_data ().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->custom_data ().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/wildcard/email.xml b/examples/cxx/hybrid/wildcard/email.xml new file mode 100644 index 0000000..75592f4 --- /dev/null +++ b/examples/cxx/hybrid/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/wildcard/email.xsd b/examples/cxx/hybrid/wildcard/email.xsd new file mode 100644 index 0000000..ca20df3 --- /dev/null +++ b/examples/cxx/hybrid/wildcard/email.xsd @@ -0,0 +1,45 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/examples/cxx/hybrid/wildcard/envelope-pimpl.cxx b/examples/cxx/hybrid/wildcard/envelope-pimpl.cxx new file mode 100644 index 0000000..16bd2e5 --- /dev/null +++ b/examples/cxx/hybrid/wildcard/envelope-pimpl.cxx @@ -0,0 +1,111 @@ +// file : examples/cxx/hybrid/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:: + _pre () + { + // Set the custom data destructor. + // + envelope_base_pimpl_state_.envelope_->custom_data ().destructor ( + &destroy_body); + + envelope_base_pimpl::_pre (); + } + + 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->custom_data ().push_back (b.release ()); + } + else if (name == "binary") + { + std::auto_ptr b (new body); + b->binary (binary_p_->post_binary ()); + env->custom_data ().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/wildcard/envelope-pimpl.hxx b/examples/cxx/hybrid/wildcard/envelope-pimpl.hxx new file mode 100644 index 0000000..06eb26c --- /dev/null +++ b/examples/cxx/hybrid/wildcard/envelope-pimpl.hxx @@ -0,0 +1,81 @@ +// file : examples/cxx/hybrid/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: + virtual void + _pre (); + + // 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/wildcard/envelope-simpl.cxx b/examples/cxx/hybrid/wildcard/envelope-simpl.cxx new file mode 100644 index 0000000..ae7bd00 --- /dev/null +++ b/examples/cxx/hybrid/wildcard/envelope-simpl.cxx @@ -0,0 +1,137 @@ +// file : examples/cxx/hybrid/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_->custom_data ().begin (); + } + + bool envelope_simpl:: + any_next () + { + envelope::custom_data_const_iterator end ( + envelope_base_simpl_state_.envelope_->custom_data ().end ()); + + // See if there is a body that we know how to serialize. + // + for (; i_ != end; ++i_) + { + body::type t = static_cast (*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 (static_cast (*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 = static_cast (*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/wildcard/envelope-simpl.hxx b/examples/cxx/hybrid/wildcard/envelope-simpl.hxx new file mode 100644 index 0000000..1de12bd --- /dev/null +++ b/examples/cxx/hybrid/wildcard/envelope-simpl.hxx @@ -0,0 +1,67 @@ +// file : examples/cxx/hybrid/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::custom_data_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/wildcard/makefile b/examples/cxx/hybrid/wildcard/makefile new file mode 100644 index 0000000..94d2fae --- /dev/null +++ b/examples/cxx/hybrid/wildcard/makefile @@ -0,0 +1,80 @@ +# file : examples/cxx/hybrid/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 +clean := $(out_base)/.clean + +# Build. +# +$(driver): $(obj) $(xsde.l) + +$(obj) $(dep): $(xsde.l.cpp-options) + +gen := $(out_base)/$(xsd:.xsd=.hxx) \ + $(out_base)/$(xsd:.xsd=.cxx) \ + $(out_base)/$(xsd:.xsd=-pskel.hxx) \ + $(out_base)/$(xsd:.xsd=-pskel.cxx) \ + $(out_base)/$(xsd:.xsd=-pimpl.hxx) \ + $(out_base)/$(xsd:.xsd=-pimpl.cxx) \ + $(out_base)/$(xsd:.xsd=-sskel.hxx) \ + $(out_base)/$(xsd:.xsd=-sskel.cxx) \ + $(out_base)/$(xsd:.xsd=-simpl.hxx) \ + $(out_base)/$(xsd:.xsd=-simpl.cxx) + +$(gen): $(out_root)/xsde/xsde +$(gen): xsde := $(out_root)/xsde/xsde +$(gen): xsde_options += --generate-parser --generate-serializer \ +--generate-aggregate --root-element-all --custom-data envelope \ +--custom-parser envelope=envelope_base_pimpl/envelope-pimpl.hxx \ +--custom-serializer envelope=envelope_base_simpl/envelope-simpl.hxx + +$(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=.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/hybrid/xsd-cxx.make) + + +# Dependencies. +# +$(call import,$(src_root)/xsde/makefile) +$(call import,$(src_root)/libxsde/xsde/makefile) diff --git a/examples/cxx/makefile b/examples/cxx/makefile new file mode 100644 index 0000000..8b4a552 --- /dev/null +++ b/examples/cxx/makefile @@ -0,0 +1,20 @@ +# file : examples/cxx/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 + +examples := hybrid parser serializer + +default := $(out_base)/ +test := $(out_base)/.test +clean := $(out_base)/.clean + +.PHONY: $(default) $(test) $(clean) + +$(default): $(addprefix $(out_base)/,$(addsuffix /,$(examples))) +$(test): $(addprefix $(out_base)/,$(addsuffix /.test,$(examples))) +$(clean): $(addprefix $(out_base)/,$(addsuffix /.clean,$(examples))) + +$(foreach e,$(examples),$(call import,$(src_base)/$e/makefile)) diff --git a/examples/cxx/parser/README b/examples/cxx/parser/README new file mode 100644 index 0000000..eaf9342 --- /dev/null +++ b/examples/cxx/parser/README @@ -0,0 +1,32 @@ +This directory contains a number of examples that show how to +use the Embedded C++/Parser 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 parse XML + documents. + +generated + Shows how to use the sample implementation and test driver + generation feature. This example does not have any hand-written + C++ code; everything is generated by the XSD/e compiler. + +library + Shows how to handle more complex data structures and construct + a custom in-memory object model. + +minimal + This example is a minimal parser implementation that is + intended to work without STL, iostream, or C++ exceptions. + +wildcard + Shows how to parse XML data matched by XML Schema wildcards (any + and anyAttribute). + +multiroot + Shows how to handle XML vocabularies with multiple root elements. + +mixed + Shows how to handle raw, "type-less content" such as mixed content + models, anyType/anySimpleType, and any/anyAttribute. diff --git a/examples/cxx/parser/generated/README b/examples/cxx/parser/generated/README new file mode 100644 index 0000000..ab7ab06 --- /dev/null +++ b/examples/cxx/parser/generated/README @@ -0,0 +1,36 @@ +This example shows how to use the sample implementation and test +driver generation feature of the Embedded C++/Parser mapping. This +example does not have any hand-written C++ code; everything is +generated by the XSD/e compiler. + +The example consists of the following files: + +library.xsd + XML Schema which describes a library of books. + +library.xml + Sample XML instance document. + +library-pskel.hxx +library-pskel.cxx + Parser skeletons generated by XSD/e from library.xsd. + +library-pimpl.hxx +library-pimpl.cxx + Sample parser implementations that print the XML data to STDOUT. + These are generated by XSD/e from library.xsd with the + --generate-print-impl option. + +library-pdriver.cxx + Sample driver for the example. It is generated by XSD/e from + library.xsd with the --generate-test-driver option. + + +To run the example on the sample XML instance document simply +execute: + +$ ./library-pdriver library.xml + +The example reads from STDIN if input file is not specified: + +$ ./library-pdriver + + + + + + + 0679760806 + The Master and Margarita + fiction + + + Mikhail Bulgakov + 1891-05-15 + 1940-03-10 + + + + + + 0679600841 + War and Peace + history + + + Leo Tolstoy + 1828-09-09 + 1910-11-20 + + + + + + 0679420290 + Crime and Punishment + philosophy + + + Fyodor Dostoevsky + 1821-11-11 + 1881-02-09 + + + + diff --git a/examples/cxx/parser/generated/library.xsd b/examples/cxx/parser/generated/library.xsd new file mode 100644 index 0000000..57654c7 --- /dev/null +++ b/examples/cxx/parser/generated/library.xsd @@ -0,0 +1,79 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/examples/cxx/parser/generated/makefile b/examples/cxx/parser/generated/makefile new file mode 100644 index 0000000..8bd0b05 --- /dev/null +++ b/examples/cxx/parser/generated/makefile @@ -0,0 +1,71 @@ +# file : examples/cxx/parser/generated/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 + +xsd := library.xsd + +obj := $(addprefix $(out_base)/,$(xsd:.xsd=-pskel.o) $(xsd:.xsd=-pimpl.o) $(xsd:.xsd=-pdriver.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)/$(xsd:.xsd=-pdriver) +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) + +gen := $(out_base)/$(xsd:.xsd=-pskel.hxx) \ + $(out_base)/$(xsd:.xsd=-pskel.ixx) \ + $(out_base)/$(xsd:.xsd=-pskel.cxx) \ + $(out_base)/$(xsd:.xsd=-pimpl.hxx) \ + $(out_base)/$(xsd:.xsd=-pimpl.cxx) \ + $(out_base)/$(xsd:.xsd=-pdriver.cxx) + +$(gen): xsde := $(out_root)/xsde/xsde +$(gen): xsde_options += --generate-print-impl --generate-test-driver \ +--force-overwrite +$(gen): $(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=-pskel.cxx.xsd.clean)) \ + $(addprefix $(out_base)/,$(xsd:.xsd=-pimpl.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) + +xsd_pimpl_suffix := -pimpl +$(call include,$(scf_root)/xsde/parser/xsd-cxx.make) + + +# Dependencies. +# +$(call import,$(src_root)/xsde/makefile) +$(call import,$(src_root)/libxsde/xsde/makefile) diff --git a/examples/cxx/parser/hello/README b/examples/cxx/parser/hello/README new file mode 100644 index 0000000..958ed1e --- /dev/null +++ b/examples/cxx/parser/hello/README @@ -0,0 +1,33 @@ +This is a "Hello, world!" example that shows how to use the +Embedded C++/Parser mapping to parse XML instance documents. + +The example consists of the following files: + +hello.xsd + XML Schema which describes "hello" instance documents. + +hello.xml + Sample XML instance document. + +hello-pskel.hxx +hello-pskel.ixx +hello-pskel.cxx + Parser skeletons generated by XSD/e from hello.xsd. + +driver.cxx + A parser implementation and a driver for the example. The + parser implementation simply prints the results to STDERR. + The driver first constructs a parser instance from the + parser implementation mentioned above and a couple of + predefined parsers for the XML Schema built-in types. + In then invokes this parser instance to parse the input + file. + +To run the example on the sample XML instance document simply +execute: + +$ ./driver hello.xml + +The example reads from STDIN if input file is not specified: + +$ ./driver +// copyright : not copyrighted - public domain + +#include +#include + +#include "hello-pskel.hxx" + +using namespace std; + +struct hello_pimpl: hello_pskel +{ + virtual void + greeting (const string& greeting) + { + greeting_ = greeting; + } + + virtual void + name (const string& name) + { + cout << greeting_ << ", " << name << "!" << endl; + } + +private: + string greeting_; +}; + + +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 + { + // Construct the parser. + // + xml_schema::string_pimpl string_p; + hello_pimpl hello_p; + + hello_p.greeting_parser (string_p); + hello_p.name_parser (string_p); + + + // Parse the XML instance document. The second argument to the + // document's constructor is the document's root element name. + // + xml_schema::document_pimpl doc_p (hello_p, "hello"); + + hello_p.pre (); + + if (argc < 2) + doc_p.parse (cin); + else + doc_p.parse (argv[1]); + + hello_p.post_hello (); + } + catch (const xml_schema::parser_exception& e) + { + cerr << input << ":" << e.line () << ":" << e.column () << ": " + << e.text () << endl; + return 1; + } + catch (const std::ios_base::failure&) + { + cerr << input << ": unable to open or read failure" << endl; + return 1; + } + + return 0; +} diff --git a/examples/cxx/parser/hello/hello.xml b/examples/cxx/parser/hello/hello.xml new file mode 100644 index 0000000..2e5aaa3 --- /dev/null +++ b/examples/cxx/parser/hello/hello.xml @@ -0,0 +1,20 @@ + + + + + + + Hello + + sun + moon + world + + diff --git a/examples/cxx/parser/hello/hello.xsd b/examples/cxx/parser/hello/hello.xsd new file mode 100644 index 0000000..f0941b7 --- /dev/null +++ b/examples/cxx/parser/hello/hello.xsd @@ -0,0 +1,22 @@ + + + + + + + + + + + + + + + + diff --git a/examples/cxx/parser/hello/makefile b/examples/cxx/parser/hello/makefile new file mode 100644 index 0000000..9067e04 --- /dev/null +++ b/examples/cxx/parser/hello/makefile @@ -0,0 +1,64 @@ +# file : examples/cxx/parser/hello/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 := hello.xsd +cxx := driver.cxx + +obj := $(addprefix $(out_base)/,$(cxx:.cxx=.o) $(xsd:.xsd=-pskel.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=-pskel.hxx) \ + $(out_base)/$(xsd:.xsd=-pskel.ixx) \ + $(out_base)/$(xsd:.xsd=-pskel.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=-pskel.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/parser/xsd-cxx.make) + + +# Dependencies. +# +$(call import,$(src_root)/xsde/makefile) +$(call import,$(src_root)/libxsde/xsde/makefile) diff --git a/examples/cxx/parser/library/README b/examples/cxx/parser/library/README new file mode 100644 index 0000000..da0a49b --- /dev/null +++ b/examples/cxx/parser/library/README @@ -0,0 +1,53 @@ +This example shows how to use the Embedded C++/Parser mapping +to construct a custom in-memory object model from XML instance +documents. + +The example consists of the following files: + +library.xsd + XML Schema which describes a library of books. + +library.xml + Sample XML instance document. + +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-pskel.hxx +library-pskel.ixx +library-pskel.cxx + Parser skeletons generated by XSD/e from library.xsd and + library.map. + +library-pimpl-mixin.hxx +library-pimpl-mixin.cxx + +library-pimpl-tiein.hxx +library-pimpl-tiein.cxx + Parser implementations (using either mixin or tiein parser + reuse style) that construct the custom in-memory object model + from an XML instance using types from library.hxx. These are + hand-written implementations of the parser skeletons defined + in library-pskel.hxx. + +driver.cxx + Driver for the example. It first constructs a parser + instance from all the individual parsers found in one of + library-pimpl-*.hxx. In then invokes this parser instance + to parse the input file and produce the in-memory object + model. Finally, it prints the content of the object model + to STDERR. + +To run the example on the sample XML instance document simply +execute: + +$ ./driver library.xml + +The example reads from STDIN if input file is not specified: + +$ ./driver +// copyright : not copyrighted - public domain + +#include + +#include "library.hxx" + +#include "library-pskel.hxx" // Get the configuration macros (XSDE_*). + +#if defined(XSDE_REUSE_STYLE_MIXIN) +# include "library-pimpl-mixin.hxx" +#elif defined(XSDE_REUSE_STYLE_TIEIN) +# include "library-pimpl-tiein.hxx" +#else +# error this example requires mixin or tiein parser reuse support +#endif + +using std::cerr; +using std::endl; + +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 library; + + + // Construct the parser. + // + xml_schema::id_pimpl id_p; + xml_schema::idref_pimpl idref_p; + xml_schema::string_pimpl string_p; + xml_schema::boolean_pimpl boolean_p; + + isbn_pimpl isbn_p; + + title_pimpl title_p; + title_p.lang_parser (string_p); + + genre_pimpl genre_p; + + author_pimpl author_p; + author_p.parsers (string_p, // name + string_p, // born + string_p, // died + idref_p); // recommends + + book_pimpl book_p; + book_p.parsers (boolean_p, // available + id_p, // id + isbn_p, // isbn + title_p, // title + genre_p, // genre + author_p); // author + + catalog_pimpl catalog_p; + catalog_p.book_parser (book_p); + + + // Parse the XML instance document. + // + xml_schema::document_pimpl doc_p ( + catalog_p, + "http://www.codesynthesis.com/library", // root element namespace + "catalog"); // root element name + + catalog_p.pre (); + + if (argc < 2) + doc_p.parse (std::cin); + else + doc_p.parse (argv[1]); + + catalog c (catalog_p.post_catalog ()); + + + // Let's print what we've got. + // + for (catalog::const_iterator bi (c.begin ()); bi != c.end (); ++bi) + { + cerr << endl + << "ID : " << bi->id () << endl + << "ISBN : " << bi->isbn () << endl + << "Title : " << bi->title () << endl + << "Genre : " << bi->genre () << endl; + + for (book::authors::const_iterator ai (bi->author ().begin ()); + ai != bi->author ().end (); + ++ai) + { + cerr << "Author : " << ai->name () << endl; + cerr << " Born : " << ai->born () << endl; + + if (!ai->died ().empty ()) + cerr << " Died : " << ai->died () << endl; + + if (!ai->recommends ().empty ()) + { + cerr << " Recommends : " << ai->recommends () << endl; + } + } + + cerr << "Available : " << std::boolalpha << bi->available () << endl; + } + } + catch (const xml_schema::parser_exception& e) + { + cerr << input << ":" << e.line () << ":" << e.column () << ": " + << e.text () << endl; + return 1; + } + catch (const std::ios_base::failure&) + { + cerr << input << ": unable to open or read failure" << endl; + return 1; + } + + return 0; +} diff --git a/examples/cxx/parser/library/library-pimpl-mixin.cxx b/examples/cxx/parser/library/library-pimpl-mixin.cxx new file mode 100644 index 0000000..ac525a2 --- /dev/null +++ b/examples/cxx/parser/library/library-pimpl-mixin.cxx @@ -0,0 +1,184 @@ +// file : examples/cxx/parser/library/library-pimpl-mixin.cxx +// author : Boris Kolpackov +// copyright : not copyrighted - public domain + +#include "library-pimpl-mixin.hxx" + +namespace library +{ + // isbn_pimpl + // + isbn isbn_pimpl:: + post_isbn () + { + return post_unsigned_int (); + } + + // title_pimpl + // + void title_pimpl:: + _pre () + { + title_.lang (""); + } + + void title_pimpl:: + lang (const std::string& lang) + { + title_.lang (lang); + } + + title title_pimpl:: + post_title () + { + title_.assign (post_string ()); + return title_; + } + + // genre_pimpl + // + genre genre_pimpl:: + post_genre () + { + genre r (romance); + std::string v (post_string ()); + + if (v == "romance") r = romance; else + if (v == "fiction") r = fiction; else + if (v == "horror") r = horror; else + if (v == "history") r = history; else + if (v == "philosophy") r = philosophy; + + return r; + } + + // person_pimpl + // + void person_pimpl:: + _pre () + { + person_.died (""); + } + + void person_pimpl:: + name (const std::string& name) + { + person_.name (name); + } + + void person_pimpl:: + born (const std::string& born) + { + person_.born (born); + } + + void person_pimpl:: + died (const std::string& died) + { + person_.died (died); + } + + person person_pimpl:: + post_person () + { + return person_; + } + + // author_pimpl + // + void author_pimpl:: + _pre () + { + author_.recommends (""); + person_pimpl::_pre (); + } + + void author_pimpl:: + recommends (const std::string& recommends) + { + author_.recommends (recommends); + } + + author author_pimpl:: + post_author () + { + person p (post_person ()); + + author_.name (p.name ()); + author_.born (p.born ()); + author_.died (p.died ()); + + return author_; + } + + // book_pimpl + // + void book_pimpl:: + _pre () + { + book_.author ().clear (); + } + + void book_pimpl:: + isbn (library::isbn isbn) + { + book_.isbn (isbn); + } + + void book_pimpl:: + title (const library::title& title) + { + book_.title (title); + } + + void book_pimpl:: + genre (library::genre genre) + { + book_.genre (genre); + } + + void book_pimpl:: + author (const library::author& author) + { + book_.author ().push_back (author); + } + + void book_pimpl:: + available (bool available) + { + book_.available (available); + } + + void book_pimpl:: + id (const std::string& id) + { + book_.id (id); + } + + book book_pimpl:: + post_book () + { + return book_; + } + + // catalog_pimpl + // + void catalog_pimpl:: + _pre () + { + catalog_.clear (); + } + + void catalog_pimpl:: + book (const library::book& book) + { + catalog_.push_back (book); + } + + catalog catalog_pimpl:: + post_catalog () + { + return catalog_; + } +} + diff --git a/examples/cxx/parser/library/library-pimpl-mixin.hxx b/examples/cxx/parser/library/library-pimpl-mixin.hxx new file mode 100644 index 0000000..e57efea --- /dev/null +++ b/examples/cxx/parser/library/library-pimpl-mixin.hxx @@ -0,0 +1,136 @@ +// file : examples/cxx/parser/library/library-pimpl-mixin.hxx +// author : Boris Kolpackov +// copyright : not copyrighted - public domain + +#ifndef LIBRARY_PIMPL_HXX +#define LIBRARY_PIMPL_HXX + +#include "library.hxx" +#include "library-pskel.hxx" + +namespace library +{ + // + // + struct isbn_pimpl: virtual isbn_pskel, xml_schema::unsigned_int_pimpl + { + virtual isbn + post_isbn (); + }; + + // + // + struct title_pimpl: virtual title_pskel, xml_schema::string_pimpl + { + virtual void + _pre (); + + virtual void + lang (const std::string&); + + virtual title + post_title (); + + private: + title title_; + }; + + // + // + struct genre_pimpl: virtual genre_pskel, xml_schema::string_pimpl + { + virtual genre + post_genre (); + }; + + // + // + struct person_pimpl: virtual person_pskel + { + virtual void + _pre (); + + virtual void + name (const std::string&); + + virtual void + born (const std::string&); + + virtual void + died (const std::string&); + + virtual person + post_person (); + + private: + person person_; + }; + + // + // + struct author_pimpl: virtual author_pskel, person_pimpl + { + virtual void + _pre (); + + virtual void + recommends (const std::string&); + + virtual author + post_author (); + + private: + author author_; + }; + + // + // + struct book_pimpl: virtual book_pskel + { + virtual void + _pre (); + + virtual void + isbn (library::isbn); + + virtual void + title (const library::title&); + + virtual void + genre (library::genre); + + virtual void + author (const library::author&); + + virtual void + available (bool); + + virtual void + id (const std::string&); + + virtual book + post_book (); + + private: + book book_; + }; + + // + // + struct catalog_pimpl: virtual catalog_pskel + { + virtual void + _pre (); + + virtual void + book (const library::book&); + + virtual catalog + post_catalog (); + + private: + catalog catalog_; + }; +} + +#endif // LIBRARY_PIMPL_HXX diff --git a/examples/cxx/parser/library/library-pimpl-tiein.cxx b/examples/cxx/parser/library/library-pimpl-tiein.cxx new file mode 100644 index 0000000..f4f54a8 --- /dev/null +++ b/examples/cxx/parser/library/library-pimpl-tiein.cxx @@ -0,0 +1,208 @@ +// file : examples/cxx/parser/library/library-pimpl-tiein.cxx +// author : Boris Kolpackov +// copyright : not copyrighted - public domain + +#include "library-pimpl-tiein.hxx" + +namespace library +{ + // isbn_pimpl + // + isbn_pimpl:: + isbn_pimpl () + : isbn_pskel (&base_impl_) + { + } + + isbn isbn_pimpl:: + post_isbn () + { + return post_unsigned_int (); + } + + // title_pimpl + // + title_pimpl:: + title_pimpl () + : title_pskel (&base_impl_) + { + } + + void title_pimpl:: + _pre () + { + title_.lang (""); + } + + void title_pimpl:: + lang (const std::string& lang) + { + title_.lang (lang); + } + + title title_pimpl:: + post_title () + { + title_.assign (post_string ()); + return title_; + } + + // genre_pimpl + // + genre_pimpl:: + genre_pimpl () + : genre_pskel (&base_impl_) + { + } + + genre genre_pimpl:: + post_genre () + { + genre r (romance); + std::string v (post_string ()); + + if (v == "romance") r = romance; else + if (v == "fiction") r = fiction; else + if (v == "horror") r = horror; else + if (v == "history") r = history; else + if (v == "philosophy") r = philosophy; + + return r; + } + + // person_pimpl + // + void person_pimpl:: + _pre () + { + person_.died (""); + } + + void person_pimpl:: + name (const std::string& name) + { + person_.name (name); + } + + void person_pimpl:: + born (const std::string& born) + { + person_.born (born); + } + + void person_pimpl:: + died (const std::string& died) + { + person_.died (died); + } + + person person_pimpl:: + post_person () + { + return person_; + } + + // author_pimpl + // + author_pimpl:: + author_pimpl () + : author_pskel (&base_impl_) + { + } + + void author_pimpl:: + _pre () + { + author_.recommends (""); + base_impl_._pre (); + } + + void author_pimpl:: + recommends (const std::string& recommends) + { + author_.recommends (recommends); + } + + author author_pimpl:: + post_author () + { + person p (post_person ()); + + author_.name (p.name ()); + author_.born (p.born ()); + author_.died (p.died ()); + + return author_; + } + + // book_pimpl + // + void book_pimpl:: + _pre () + { + book_.author ().clear (); + } + + void book_pimpl:: + isbn (library::isbn isbn) + { + book_.isbn (isbn); + } + + void book_pimpl:: + title (const library::title& title) + { + book_.title (title); + } + + void book_pimpl:: + genre (library::genre genre) + { + book_.genre (genre); + } + + void book_pimpl:: + author (const library::author& author) + { + book_.author ().push_back (author); + } + + void book_pimpl:: + available (bool available) + { + book_.available (available); + } + + void book_pimpl:: + id (const std::string& id) + { + book_.id (id); + } + + book book_pimpl:: + post_book () + { + return book_; + } + + // catalog_pimpl + // + void catalog_pimpl:: + _pre () + { + catalog_.clear (); + } + + void catalog_pimpl:: + book (const library::book& book) + { + catalog_.push_back (book); + } + + catalog catalog_pimpl:: + post_catalog () + { + return catalog_; + } +} + diff --git a/examples/cxx/parser/library/library-pimpl-tiein.hxx b/examples/cxx/parser/library/library-pimpl-tiein.hxx new file mode 100644 index 0000000..423bc91 --- /dev/null +++ b/examples/cxx/parser/library/library-pimpl-tiein.hxx @@ -0,0 +1,152 @@ +// file : examples/cxx/parser/library/library-pimpl-tiein.hxx +// author : Boris Kolpackov +// copyright : not copyrighted - public domain + +#ifndef LIBRARY_PIMPL_HXX +#define LIBRARY_PIMPL_HXX + +#include "library.hxx" +#include "library-pskel.hxx" + +namespace library +{ + // + // + struct isbn_pimpl: isbn_pskel + { + isbn_pimpl (); + + virtual isbn + post_isbn (); + + private: + xml_schema::unsigned_int_pimpl base_impl_; + }; + + // + // + struct title_pimpl: title_pskel + { + title_pimpl (); + + virtual void + _pre (); + + virtual void + lang (const std::string&); + + virtual title + post_title (); + + private: + title title_; + xml_schema::string_pimpl base_impl_; + }; + + // + // + struct genre_pimpl: genre_pskel + { + genre_pimpl (); + + virtual genre + post_genre (); + + private: + xml_schema::string_pimpl base_impl_; + }; + + // + // + struct person_pimpl: person_pskel + { + virtual void + _pre (); + + virtual void + name (const std::string&); + + virtual void + born (const std::string&); + + virtual void + died (const std::string&); + + virtual person + post_person (); + + private: + person person_; + }; + + // + // + struct author_pimpl: author_pskel + { + author_pimpl (); + + virtual void + _pre (); + + virtual void + recommends (const std::string&); + + virtual author + post_author (); + + private: + person_pimpl base_impl_; + author author_; + }; + + // + // + struct book_pimpl: book_pskel + { + virtual void + _pre (); + + virtual void + isbn (library::isbn); + + virtual void + title (const library::title&); + + virtual void + genre (library::genre); + + virtual void + author (const library::author&); + + virtual void + available (bool); + + virtual void + id (const std::string&); + + virtual book + post_book (); + + private: + book book_; + }; + + // + // + struct catalog_pimpl: catalog_pskel + { + virtual void + _pre (); + + virtual void + book (const library::book&); + + virtual catalog + post_catalog (); + + private: + catalog catalog_; + }; +} + +#endif // LIBRARY_PIMPL_HXX diff --git a/examples/cxx/parser/library/library.hxx b/examples/cxx/parser/library/library.hxx new file mode 100644 index 0000000..fb6cc1d --- /dev/null +++ b/examples/cxx/parser/library/library.hxx @@ -0,0 +1,242 @@ +// file : examples/cxx/parser/library/library.hxx +// author : Boris Kolpackov +// copyright : not copyrighted - public domain + +#ifndef LIBRARY_HXX +#define LIBRARY_HXX + +#include +#include + +namespace library +{ + // + // + typedef unsigned int isbn; + + + // + // + struct title: std::string + { + // 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 + { + // 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 + { + // recommends + // + const std::string& + recommends () const + { + return recommends_; + } + + void + recommends (const std::string& recommends) + { + recommends_ = recommends; + } + + private: + std::string recommends_; + }; + + + // + // + struct book + { + // isbn + // + library::isbn + isbn () const + { + return isbn_; + } + + void + isbn (const library::isbn& isbn) + { + isbn_ = isbn; + } + + + // title + // + 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 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 catalog; +} + +#endif // LIBRARY_HXX diff --git a/examples/cxx/parser/library/library.map b/examples/cxx/parser/library/library.map new file mode 100644 index 0000000..87a1d53 --- /dev/null +++ b/examples/cxx/parser/library/library.map @@ -0,0 +1,16 @@ +# file : examples/cxx/parser/library/library.map +# author : Boris Kolpackov +# copyright : not copyrighted - public domain + +namespace http://www.codesynthesis.com/library library +{ + include "library.hxx"; + + isbn isbn isbn; + title title; + genre genre genre; + person person; + author author; + book book; + catalog catalog; +} diff --git a/examples/cxx/parser/library/library.xml b/examples/cxx/parser/library/library.xml new file mode 100644 index 0000000..2d9069c --- /dev/null +++ b/examples/cxx/parser/library/library.xml @@ -0,0 +1,53 @@ + + + + + + + + 0679760806 + The Master and Margarita + fiction + + + Mikhail Bulgakov + 1891-05-15 + 1940-03-10 + + + + + + 0679600841 + War and Peace + history + + + Leo Tolstoy + 1828-09-09 + 1910-11-20 + + + + + + 0679420290 + Crime and Punishment + philosophy + + + Fyodor Dostoevsky + 1821-11-11 + 1881-02-09 + + + + diff --git a/examples/cxx/parser/library/library.xsd b/examples/cxx/parser/library/library.xsd new file mode 100644 index 0000000..57654c7 --- /dev/null +++ b/examples/cxx/parser/library/library.xsd @@ -0,0 +1,79 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/examples/cxx/parser/library/makefile b/examples/cxx/parser/library/makefile new file mode 100644 index 0000000..3df256c --- /dev/null +++ b/examples/cxx/parser/library/makefile @@ -0,0 +1,72 @@ +# file : examples/cxx/parser/library/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 := library.xsd +cxx := driver.cxx + +ifeq ($(xsde_reuse_style),mixin) +cxx += library-pimpl-mixin.cxx +else +cxx += library-pimpl-tiein.cxx +endif + +obj := $(addprefix $(out_base)/,$(cxx:.cxx=.o) $(xsd:.xsd=-pskel.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=-pskel.hxx) \ + $(out_base)/$(xsd:.xsd=-pskel.ixx) \ + $(out_base)/$(xsd:.xsd=-pskel.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=-pskel.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/parser/xsd-cxx.make) + + +# Dependencies. +# +$(call import,$(src_root)/xsde/makefile) +$(call import,$(src_root)/libxsde/xsde/makefile) diff --git a/examples/cxx/parser/makefile b/examples/cxx/parser/makefile new file mode 100644 index 0000000..5a81a72 --- /dev/null +++ b/examples/cxx/parser/makefile @@ -0,0 +1,53 @@ +# file : examples/cxx/parser/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 + +examples := + +ifneq ($(xsde_reuse_style),none) +examples += generated +endif + +ifeq ($(xsde_stl),y) +ifeq ($(xsde_iostream),y) +ifeq ($(xsde_exceptions),y) + +examples += hello + +ifneq ($(xsde_reuse_style),none) +examples += library multiroot + +ifeq ($(xsde_polymorphic),y) +examples += polymorphism polyroot +endif + +endif + +ifeq ($(xsde_reuse_style),tiein) +examples += mixed 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/parser/minimal/README b/examples/cxx/parser/minimal/README new file mode 100644 index 0000000..a525533 --- /dev/null +++ b/examples/cxx/parser/minimal/README @@ -0,0 +1,51 @@ +This example is a minimal parser 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.xml + Sample XML instance document. + +gender.hxx + C++ gender enum that corresponds to the gender types + in people.xsd. + +people.map + Type map. It maps XML Schema gender type defined in + people.xsd to C++ gender enum defined in gender.hxx. + +people-pskel.hxx +people-pskel.ixx +people-pskel.cxx + Parser skeletons generated by XSD/e from people.xsd and + people.map. The --no-stl and --no-exceptions options + were used to produce these files. + +people-pimpl-mixin.hxx + +people-pimpl-tiein.hxx + Parser implementations (using either mixin or tiein parser + reuse style) that prints the results to STDERR. These are + hand-written implementations of the parser skeletons defined + in people-pskel.hxx. + +driver.cxx + Driver for the example. It first constructs a parser instance + from the parser implementation mentioned above and a couple of + predefined parsers for the XML Schema built-in types. In then + invokes this parser instance to parse the input file. It also + shows how to handle parsing and validation errors using error + codes. + +To run the example on the sample XML instance document simply +execute: + +$ ./driver people.xml + +The example reads from STDIN if input file is not specified: + +$ ./driver +// copyright : not copyrighted - public domain + +#include + +#include "people-pskel.hxx" // Get the configuration macros (XSDE_*). + +#if defined(XSDE_REUSE_STYLE_MIXIN) +# include "people-pimpl-mixin.hxx" +#elif defined(XSDE_REUSE_STYLE_TIEIN) +# include "people-pimpl-tiein.hxx" +#else +# error this example requires mixin or tiein parser reuse support +#endif + +int +main (int argc, char* argv[]) +{ + const char* input; + + if (argc < 2) + { + input = "STDIN"; + fprintf (stderr, "XML file not specified, reading from STDIN\n"); + } + else + input = argv[1]; + + // Construct the parser. + // + xml_schema::unsigned_short_pimpl unsigned_short_p; + xml_schema::string_pimpl string_p; + + gender_pimpl gender_p; + person_pimpl person_p; + people_pimpl people_p; + + person_p.parsers (string_p, string_p, gender_p, unsigned_short_p); + people_p.parsers (person_p); + + // Open the file or use STDIN. + // + FILE* f = argc > 1 ? fopen (argv[1], "rb") : stdin; + + if (f == 0) + { + fprintf (stderr, "%s: unable to open\n", input); + return 1; + } + + // Parse. + // + typedef xml_schema::parser_error error; + error e; + bool io_error = false; + + do + { + xml_schema::document_pimpl doc_p (people_p, "people"); + + if (e = doc_p._error ()) + break; + + people_p.pre (); + + if (e = people_p._error ()) + break; + + char buf[4096]; + + do + { + size_t s = fread (buf, 1, sizeof (buf), f); + + if (s != sizeof (buf) && ferror (f)) + { + io_error = true; + break; + } + + doc_p.parse (buf, s, feof (f) != 0); + e = doc_p._error (); + + } while (!e && !feof (f)); + + if (io_error || e) + break; + + people_p.post_people (); + + e = people_p._error (); + + } while (false); + + if (argc > 1) + fclose (f); + + // Handle errors. + // + + if (io_error) + { + fprintf (stderr, "%s: read failure\n", input); + return 1; + } + + if (e) + { + switch (e.type ()) + { + case error::sys: + { + fprintf (stderr, "%s: %s\n", input, e.sys_text ()); + break; + } + case error::xml: + { + fprintf (stderr, "%s:%lu:%lu: %s\n", + input, e.line (), e.column (), e.xml_text ()); + break; + } +#ifdef XSDE_PARSER_VALIDATION + case error::schema: + { + fprintf (stderr, "%s:%lu:%lu: %s\n", + input, e.line (), e.column (), e.schema_text ()); + break; + } +#endif + case error::app: + { + fprintf (stderr, "%s:%lu:%lu: application error %d\n", + input, e.line (), e.column (), e.app_code ()); + break; + } + default: + break; + } + + return 1; + } + + return 0; +} diff --git a/examples/cxx/parser/minimal/gender.hxx b/examples/cxx/parser/minimal/gender.hxx new file mode 100644 index 0000000..d348ccd --- /dev/null +++ b/examples/cxx/parser/minimal/gender.hxx @@ -0,0 +1,14 @@ +// file : examples/cxx/parser/minimal/gender.hxx +// author : Boris Kolpackov +// copyright : not copyrighted - public domain + +#ifndef GENDER_HXX +#define GENDER_HXX + +enum gender +{ + male, + female +}; + +#endif // GENDER_HXX diff --git a/examples/cxx/parser/minimal/makefile b/examples/cxx/parser/minimal/makefile new file mode 100644 index 0000000..1f0466c --- /dev/null +++ b/examples/cxx/parser/minimal/makefile @@ -0,0 +1,66 @@ +# file : examples/cxx/parser/minimal/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 := people.xsd +cxx := driver.cxx + +obj := $(addprefix $(out_base)/,$(cxx:.cxx=.o) $(xsd:.xsd=-pskel.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=-pskel.hxx) \ + $(out_base)/$(xsd:.xsd=-pskel.ixx) \ + $(out_base)/$(xsd:.xsd=-pskel.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=-pskel.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/parser/xsd-cxx.make) + + +# Dependencies. +# +$(call import,$(src_root)/xsde/makefile) +$(call import,$(src_root)/libxsde/xsde/makefile) diff --git a/examples/cxx/parser/minimal/people-pimpl-mixin.hxx b/examples/cxx/parser/minimal/people-pimpl-mixin.hxx new file mode 100644 index 0000000..eb2c331 --- /dev/null +++ b/examples/cxx/parser/minimal/people-pimpl-mixin.hxx @@ -0,0 +1,82 @@ +// file : examples/cxx/parser/people/people-pimpl-mixin.hxx +// author : Boris Kolpackov +// copyright : not copyrighted - public domain + +#ifndef PEOPLE_PIMPL_HXX +#define PEOPLE_PIMPL_HXX + +#include "gender.hxx" +#include "people-pskel.hxx" + +struct gender_pimpl: virtual gender_pskel, xml_schema::string_pimpl +{ + virtual gender + post_gender () + { + char* s = post_string (); + + if (!_error ()) + { + gender g = strcmp (s, "male") ? female : male; + + delete[] s; + return g; + } + else + return male; // This value will never be used. + } +}; + +struct person_pimpl: virtual person_pskel +{ + virtual void + first_name (char* n) + { + printf ("first: %s\n", n); + delete[] n; + } + + virtual void + last_name (char* n) + { + printf ("last: %s\n", n); + delete[] n; + } + + virtual void + gender (::gender g) + { + switch (g) + { + case male: + { + printf ("gender: male\n"); + break; + } + case female: + { + printf ("gender: female\n"); + break; + } + } + } + + virtual void + age (unsigned short a) + { + printf ("age: %hu\n", a); + } +}; + +struct people_pimpl: virtual people_pskel +{ + virtual void + person () + { + // Add an extra newline after each person record. + // + printf ("\n"); + } +}; + +#endif // PEOPLE_PIMPL_HXX diff --git a/examples/cxx/parser/minimal/people-pimpl-tiein.hxx b/examples/cxx/parser/minimal/people-pimpl-tiein.hxx new file mode 100644 index 0000000..154c861 --- /dev/null +++ b/examples/cxx/parser/minimal/people-pimpl-tiein.hxx @@ -0,0 +1,90 @@ +// file : examples/cxx/parser/people/people-pimpl-tiein.hxx +// author : Boris Kolpackov +// copyright : not copyrighted - public domain + +#ifndef PEOPLE_PIMPL_HXX +#define PEOPLE_PIMPL_HXX + +#include "gender.hxx" +#include "people-pskel.hxx" + +struct gender_pimpl: gender_pskel +{ + gender_pimpl () + : gender_pskel (&base_impl_) + { + } + + virtual gender + post_gender () + { + char* s = post_string (); + + if (!_error ()) + { + gender g = strcmp (s, "male") ? female : male; + + delete[] s; + return g; + } + else + return male; // This value will never be used. + } + +private: + xml_schema::string_pimpl base_impl_; +}; + +struct person_pimpl: person_pskel +{ + virtual void + first_name (char* n) + { + printf ("first: %s\n", n); + delete[] n; + } + + virtual void + last_name (char* n) + { + printf ("last: %s\n", n); + delete[] n; + } + + virtual void + gender (::gender g) + { + switch (g) + { + case male: + { + printf ("gender: male\n"); + break; + } + case female: + { + printf ("gender: female\n"); + break; + } + } + } + + virtual void + age (unsigned short a) + { + printf ("age: %hu\n", a); + } +}; + +struct people_pimpl: people_pskel +{ + virtual void + person () + { + // Add an extra newline after each person record. + // + printf ("\n"); + } +}; + +#endif // PEOPLE_PIMPL_HXX diff --git a/examples/cxx/parser/minimal/people.map b/examples/cxx/parser/minimal/people.map new file mode 100644 index 0000000..05558a1 --- /dev/null +++ b/examples/cxx/parser/minimal/people.map @@ -0,0 +1,7 @@ +# file : examples/cxx/parser/minimal/people.map +# author : Boris Kolpackov +# copyright : not copyrighted - public domain + +include "gender.hxx"; + +gender ::gender ::gender; diff --git a/examples/cxx/parser/minimal/people.xml b/examples/cxx/parser/minimal/people.xml new file mode 100644 index 0000000..fce688c --- /dev/null +++ b/examples/cxx/parser/minimal/people.xml @@ -0,0 +1,28 @@ + + + + + + + + John + Doe + male + 32 + + + + Jane + Doe + female + 28 + + + diff --git a/examples/cxx/parser/minimal/people.xsd b/examples/cxx/parser/minimal/people.xsd new file mode 100644 index 0000000..d2e8f47 --- /dev/null +++ b/examples/cxx/parser/minimal/people.xsd @@ -0,0 +1,37 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/examples/cxx/parser/mixed/README b/examples/cxx/parser/mixed/README new file mode 100644 index 0000000..69d2b07 --- /dev/null +++ b/examples/cxx/parser/mixed/README @@ -0,0 +1,54 @@ +This example shows how to handle "type-less content" such as +mixed content models, xsd:anyType/xsd:anySimpleType, and +xsd:any/xsd:anyAttribute in the Embedded C++/Parser mapping. + +In this example we use mixed content model to describe text +with embedded links, e.g., + + This paragraph talks about time. + +The example transforms such text into plain text with +references, e.g., + + This paragraph talks about time[0]. + + [0] uri + +The example consists of the following files: + +text.xsd + XML Schema which describes "text with links" instance + documents. + +text.xml + Sample XML instance document. + +anchor.hxx + Anchor type that captures the information about a link. + +text.map + Type map. It maps XML Schema anchor types defined in + text.xsd to C++ anchor class defined in anchor.hxx. + +text-pskel.hxx +text-pskel.ixx +text-pskel.cxx + Parser skeletons generated by XSD/e from text.xsd and + text.map. + +driver.cxx + A parser implementation and a driver for the example. The + parser implementation prints the transformed text to STDOUT. + The driver first constructs a parser instance from the parser + implementation mentioned above and a couple of predefined + parsers for the XML Schema built-in types. In then invokes + this parser instance to parse the input file. + +To run the example on the sample XML instance document simply +execute: + +$ ./driver text.xml + +The example reads from STDIN if input file is not specified: + +$ ./driver +// copyright : not copyrighted - public domain + +#ifndef ANCHOR_HXX +#define ANCHOR_HXX + +#include + +struct anchor +{ + anchor (const std::string& text, const std::string& uri) + : uri_ (uri), text_ (text) + { + } + + const std::string& + text () const + { + return text_; + } + + const std::string& + uri () const + { + return uri_; + } + +private: + std::string uri_; + std::string text_; +}; + +#endif // ANCHOR_HXX diff --git a/examples/cxx/parser/mixed/driver.cxx b/examples/cxx/parser/mixed/driver.cxx new file mode 100644 index 0000000..13877b0 --- /dev/null +++ b/examples/cxx/parser/mixed/driver.cxx @@ -0,0 +1,123 @@ +// file : examples/cxx/parser/mixed/driver.cxx +// author : Boris Kolpackov +// copyright : not copyrighted - public domain + +#include +#include +#include + +#include "anchor.hxx" +#include "text-pskel.hxx" + +#ifndef XSDE_REUSE_STYLE_TIEIN +# error this example requires the tiein parser reuse support +#endif + +using namespace std; + +struct anchor_pimpl: anchor_pskel +{ + anchor_pimpl () + : anchor_pskel (&base_impl_) + { + } + + virtual void + href (const std::string& uri) + { + uri_ = uri; + } + + virtual anchor + post_anchor () + { + return anchor (post_string (), uri_); + } + +private: + xml_schema::string_pimpl base_impl_; + std::string uri_; +}; + + +struct text_pimpl: text_pskel +{ + virtual void + a (const anchor& a) + { + cout << a.text () << "[" << anchors_.size () << "]"; + anchors_.push_back (a); + } + + virtual void + _any_characters (const xml_schema::ro_string& s) + { + cout << s; + } + + virtual void + post_text () + { + for (anchors::const_iterator i (anchors_.begin ()); + i != anchors_.end (); + ++i) + { + cout << "[" << i - anchors_.begin () << "] " << i->uri () << endl; + } + } + +private: + typedef vector anchors; + anchors anchors_; +}; + + +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 + { + // Construct the parser. + // + xml_schema::string_pimpl string_p; + anchor_pimpl anchor_p; + text_pimpl text_p; + + anchor_p.href_parser (string_p); + text_p.a_parser (anchor_p); + + xml_schema::document_pimpl doc_p (text_p, "text"); + + text_p.pre (); + + if (argc < 2) + doc_p.parse (cin); + else + doc_p.parse (argv[1]); + + text_p.post_text (); + } + catch (const xml_schema::parser_exception& e) + { + cerr << input << ":" << e.line () << ":" << e.column () << ": " + << e.text () << endl; + return 1; + } + catch (const std::ios_base::failure&) + { + cerr << input << ": unable to open or read failure" << endl; + return 1; + } + + return 0; +} diff --git a/examples/cxx/parser/mixed/makefile b/examples/cxx/parser/mixed/makefile new file mode 100644 index 0000000..f41fae3 --- /dev/null +++ b/examples/cxx/parser/mixed/makefile @@ -0,0 +1,66 @@ +# file : examples/cxx/parser/mixed/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 := text.xsd +cxx := driver.cxx + +obj := $(addprefix $(out_base)/,$(cxx:.cxx=.o) $(xsd:.xsd=-pskel.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=-pskel.hxx) \ + $(out_base)/$(xsd:.xsd=-pskel.ixx) \ + $(out_base)/$(xsd:.xsd=-pskel.cxx) + +$(skel): xsde := $(out_root)/xsde/xsde +$(skel): xsde_options += --type-map $(src_base)/text.map + +$(skel): $(out_root)/xsde/xsde $(src_base)/text.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=-pskel.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/parser/xsd-cxx.make) + + +# Dependencies. +# +$(call import,$(src_root)/xsde/makefile) +$(call import,$(src_root)/libxsde/xsde/makefile) diff --git a/examples/cxx/parser/mixed/text.map b/examples/cxx/parser/mixed/text.map new file mode 100644 index 0000000..206d72e --- /dev/null +++ b/examples/cxx/parser/mixed/text.map @@ -0,0 +1,7 @@ +# file : examples/cxx/parser/mixed/text.map +# author : Boris Kolpackov +# copyright : not copyrighted - public domain + +include "anchor.hxx"; + +anchor anchor; diff --git a/examples/cxx/parser/mixed/text.xml b/examples/cxx/parser/mixed/text.xml new file mode 100644 index 0000000..97d4d21 --- /dev/null +++ b/examples/cxx/parser/mixed/text.xml @@ -0,0 +1,18 @@ + + + + + + +The first paragraph of this text talks about time. + +And this paragraph talks about space. + + diff --git a/examples/cxx/parser/mixed/text.xsd b/examples/cxx/parser/mixed/text.xsd new file mode 100644 index 0000000..4929964 --- /dev/null +++ b/examples/cxx/parser/mixed/text.xsd @@ -0,0 +1,29 @@ + + + + + + + + + + + + + + + + + + + + + + + diff --git a/examples/cxx/parser/multiroot/README b/examples/cxx/parser/multiroot/README new file mode 100644 index 0000000..817e522 --- /dev/null +++ b/examples/cxx/parser/multiroot/README @@ -0,0 +1,61 @@ +This example shows how to handle XML vocabularies with multiple +root elements using the Embedded C++/Parser mapping. + +The example consists of the following files: + +protocol.xsd + XML Schema which defines a simple bank account protocol with + requests such as withdraw and deposit. + +balance.xml +withdraw.xml +deposit.xml + Sample XML instances for the protocol requests. + +protocol.hxx + C++ types that describe the protocol requests. These are + hand-written. + +protocol.map + Type map. It maps XML Schema types defined in protocol.xsd + to the C++ types defined in protocol.hxx. + +protocol-pskel.hxx +protocol-pskel.cxx + Parser skeletons generated by XSD/e from protocol.xsd and + protocol.map. + +protocol-pimpl-mixin.hxx +protocol-pimpl-mixin.cxx + +protocol-pimpl-tiein.hxx +protocol-pimpl-tiein.cxx + Parser implementations (using either mixin or tiein parser + reuse style) that construct the custom object model from an + XML instance using the types from protocol.hxx. These are + hand-written implementations of the parser skeletons defined + in protocol-pskel.hxx. + +driver.cxx + Driver for the example. It implements a custom document parser + that determines which request is being parsed and uses the + corresponding parser implementation. The document parser + intentionally does not support the deposit request to show + how to handle unknown documents. The driver first constructs + a parser instance from all the individual parsers found in one + of protocol-pimpl-*.hxx. In then invokes this parser instance + to parse the input file and produce the in-memory object model. + Finally, it prints the contents of the object model to STDERR. + +To run the example on the sample XML request documents simply +execute: + +$ ./driver balance.xml +$ ./driver withdraw.xml +$ ./driver deposit.xml + +The example reads from STDIN if input file is not specified: + +$ ./driver + + + + + + 123456789 + + diff --git a/examples/cxx/parser/multiroot/deposit.xml b/examples/cxx/parser/multiroot/deposit.xml new file mode 100644 index 0000000..3043c52 --- /dev/null +++ b/examples/cxx/parser/multiroot/deposit.xml @@ -0,0 +1,18 @@ + + + + + + + 123456789 + 1000000 + + diff --git a/examples/cxx/parser/multiroot/driver.cxx b/examples/cxx/parser/multiroot/driver.cxx new file mode 100644 index 0000000..32aced2 --- /dev/null +++ b/examples/cxx/parser/multiroot/driver.cxx @@ -0,0 +1,245 @@ +// file : examples/cxx/parser/multiroot/driver.cxx +// author : Boris Kolpackov +// copyright : not copyrighted - public domain + +#include // std::auto_ptr +#include + +#include "protocol.hxx" +#include "protocol-pskel.hxx" // Get the configuration macros (XSDE_*). + +#if defined(XSDE_REUSE_STYLE_MIXIN) +# include "protocol-pimpl-mixin.hxx" +#elif defined(XSDE_REUSE_STYLE_TIEIN) +# include "protocol-pimpl-tiein.hxx" +#else +# error this example requires mixin or tiein parser reuse support +#endif + +using std::cerr; +using std::endl; +using xml_schema::ro_string; + +namespace protocol +{ + // We are going to use our own "type ids" for the request + // types. You could instead use dynamic_cast if your system + // provides RTTI. + // + enum request_type + { + unknown_type, + balance_type, + withdraw_type + }; + + // Customize the xml_schema::document_pimpl object to handle our protocol + // vocabulary with multiple root elements. + // + class document_pimpl: public xml_schema::document_pimpl + { + public: + document_pimpl (balance_pskel& balance_p, withdraw_pskel& withdraw_p) + : result_type_ (unknown_type), + balance_p_ (balance_p), + withdraw_p_ (withdraw_p) + { + } + + request_type + result_type () const + { + return result_type_; + } + + request* + result () + { + return result_.release (); + } + + protected: + // This function is called to obtain the root element type parser. + // If the returned pointed is 0 then the whole document content + // is ignored. Note that the signature of this function varies + // depending on whether the runtime was built with polymorphism + // support. + // + virtual xml_schema::parser_base* +#ifndef XSDE_POLYMORPHIC + start_root_element (const ro_string& ns, + const ro_string& name) +#else + start_root_element (const ro_string& ns, + const ro_string& name, + const char* /* xsi:type */) +#endif + { + if (ns == "http://www.codesynthesis.com/protocol") + { + if (name == "balance") + { + balance_p_.pre (); + return &balance_p_; + } + else if (name == "withdraw") + { + balance_p_.pre (); + return &withdraw_p_; + } + + cerr << "ignoring unknown request: " << name << endl; + return 0; + } + else + { + // This document is from the wrong namespace. If the runtime and + // the generated code are built with validation enabled then we + // can set an XML Schema error. + // +#ifdef XSDE_PARSER_VALIDATION + context_.schema_error ( + xml_schema::parser_schema_error::unexpected_element); +#endif + return 0; + } + } + + // This function is called to indicate the completion of document + // parsing. The parser argument contains the pointer returned by + // start_root_element. + // + virtual void + end_root_element (const ro_string& /* ns */, + const ro_string& /* name */, + xml_schema::parser_base* parser) + { + // We could have handled the result directly in this function + // instead of storing it in the result_ variable. + // + if (parser == &balance_p_) + { + result_type_ = balance_type; + result_.reset (balance_p_.post_balance ()); + } + else if (parser == &withdraw_p_) + { + result_type_ = withdraw_type; + result_.reset (withdraw_p_.post_withdraw ()); + } + else + { + result_type_ = unknown_type; + result_.reset (0); + } + } + + + public: + // 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 root parsers. We can also get smarter here by caching + // the parser that was used last and only reset that. Note + // that you always need to call _reset() from the base. + // + virtual void + reset () + { + xml_schema::document_pimpl::reset (); + + balance_p_._reset (); + withdraw_p_._reset (); + } + + private: + request_type result_type_; + std::auto_ptr result_; + + balance_pskel& balance_p_; + withdraw_pskel& withdraw_p_; + }; +} + + +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 protocol; + + // Construct the parser. + // + xml_schema::unsigned_int_pimpl unsigned_int_p; + + balance_pimpl balance_p; + withdraw_pimpl withdraw_p; + + balance_p.parsers (unsigned_int_p); // account + + withdraw_p.parsers (unsigned_int_p, // account + unsigned_int_p); // amount + + // Parse the XML instance document. + // + document_pimpl doc_p (balance_p, withdraw_p); + + // pre() and post() will be called as part of the start_root_element() + // and end_root_element() calls. + // + if (argc < 2) + doc_p.parse (std::cin); + else + doc_p.parse (argv[1]); + + std::auto_ptr r (doc_p.result ()); + request_type t = doc_p.result_type (); + + // Let's print what we've got. + // + switch (t) + { + case balance_type: + { + balance* b = static_cast (r.get ()); + cerr << "balance request for acc# " << b->account () << endl; + break; + } + case withdraw_type: + { + withdraw* w = static_cast (r.get ()); + cerr << "withdrawal request for acc# " << w->account () << ", " + << "amount: " << w->amount () << endl; + break; + } + case unknown_type: + { + cerr << "unknown request" << endl; + break; + } + } + } + catch (const xml_schema::parser_exception& e) + { + cerr << input << ":" << e.line () << ":" << e.column () << ": " + << e.text () << endl; + return 1; + } + catch (const std::ios_base::failure&) + { + cerr << input << ": unable to open or read failure" << endl; + return 1; + } + + return 0; +} diff --git a/examples/cxx/parser/multiroot/makefile b/examples/cxx/parser/multiroot/makefile new file mode 100644 index 0000000..44e8980 --- /dev/null +++ b/examples/cxx/parser/multiroot/makefile @@ -0,0 +1,71 @@ +# file : examples/cxx/parser/multiroot/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 := protocol.xsd +cxx := driver.cxx + +ifeq ($(xsde_reuse_style),mixin) +cxx += protocol-pimpl-mixin.cxx +else +cxx += protocol-pimpl-tiein.cxx +endif + +obj := $(addprefix $(out_base)/,$(cxx:.cxx=.o) $(xsd:.xsd=-pskel.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=-pskel.hxx) \ + $(out_base)/$(xsd:.xsd=-pskel.ixx) \ + $(out_base)/$(xsd:.xsd=-pskel.cxx) + +$(skel): xsde := $(out_root)/xsde/xsde +$(skel): xsde_options += --type-map $(src_base)/protocol.map +$(skel): $(out_root)/xsde/xsde $(src_base)/protocol.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=-pskel.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/parser/xsd-cxx.make) + + +# Dependencies. +# +$(call import,$(src_root)/xsde/makefile) +$(call import,$(src_root)/libxsde/xsde/makefile) diff --git a/examples/cxx/parser/multiroot/protocol-pimpl-mixin.cxx b/examples/cxx/parser/multiroot/protocol-pimpl-mixin.cxx new file mode 100644 index 0000000..3cfd0b0 --- /dev/null +++ b/examples/cxx/parser/multiroot/protocol-pimpl-mixin.cxx @@ -0,0 +1,47 @@ +// file : examples/cxx/parser/multiroot/protocol-pimpl-mixin.cxx +// author : Boris Kolpackov +// copyright : not copyrighted - public domain + +#include "protocol-pimpl-mixin.hxx" + +namespace protocol +{ + // request_pimpl + // + void request_pimpl:: + account (unsigned int account) + { + account_ = account; + } + + request* request_pimpl:: + post_request () + { + // This parser is never used directly. + // + return 0; + } + + // balance_pimpl + // + balance* balance_pimpl:: + post_balance () + { + return new balance (account_); + } + + // withdraw_pimpl + // + void withdraw_pimpl:: + amount (unsigned int amount) + { + amount_ = amount; + } + + withdraw* withdraw_pimpl:: + post_withdraw () + { + return new withdraw (account_, amount_); + } +} + diff --git a/examples/cxx/parser/multiroot/protocol-pimpl-mixin.hxx b/examples/cxx/parser/multiroot/protocol-pimpl-mixin.hxx new file mode 100644 index 0000000..dc26e9a --- /dev/null +++ b/examples/cxx/parser/multiroot/protocol-pimpl-mixin.hxx @@ -0,0 +1,49 @@ +// file : examples/cxx/parser/multiroot/protocol-pimpl-mixin.hxx +// author : Boris Kolpackov +// copyright : not copyrighted - public domain + +#ifndef PROTOCOL_PIMPL_HXX +#define PROTOCOL_PIMPL_HXX + +#include "protocol.hxx" +#include "protocol-pskel.hxx" + +namespace protocol +{ + class request_pimpl: public virtual request_pskel + { + public: + virtual void + account (unsigned int); + + virtual request* + post_request (); + + protected: + unsigned int account_; + }; + + class balance_pimpl: public virtual balance_pskel, + public request_pimpl + { + public: + virtual balance* + post_balance (); + }; + + class withdraw_pimpl: public virtual withdraw_pskel, + public request_pimpl + { + public: + virtual void + amount (unsigned int); + + virtual withdraw* + post_withdraw (); + + private: + unsigned int amount_; + }; +} + +#endif // PROTOCOL_PIMPL_HXX diff --git a/examples/cxx/parser/multiroot/protocol-pimpl-tiein.cxx b/examples/cxx/parser/multiroot/protocol-pimpl-tiein.cxx new file mode 100644 index 0000000..def6f98 --- /dev/null +++ b/examples/cxx/parser/multiroot/protocol-pimpl-tiein.cxx @@ -0,0 +1,59 @@ +// file : examples/cxx/parser/multiroot/protocol-pimpl-tiein.cxx +// author : Boris Kolpackov +// copyright : not copyrighted - public domain + +#include "protocol-pimpl-tiein.hxx" + +namespace protocol +{ + // request_pimpl + // + void request_pimpl:: + account (unsigned int account) + { + account_ = account; + } + + request* request_pimpl:: + post_request () + { + // This parser is never used directly. + // + return 0; + } + + // balance_pimpl + // + balance_pimpl:: + balance_pimpl () + : balance_pskel (&base_impl_) + { + } + + balance* balance_pimpl:: + post_balance () + { + return new balance (base_impl_.account_); + } + + // withdraw_pimpl + // + withdraw_pimpl:: + withdraw_pimpl () + : withdraw_pskel (&base_impl_) + { + } + + void withdraw_pimpl:: + amount (unsigned int amount) + { + amount_ = amount; + } + + withdraw* withdraw_pimpl:: + post_withdraw () + { + return new withdraw (base_impl_.account_, amount_); + } +} + diff --git a/examples/cxx/parser/multiroot/protocol-pimpl-tiein.hxx b/examples/cxx/parser/multiroot/protocol-pimpl-tiein.hxx new file mode 100644 index 0000000..3a18da0 --- /dev/null +++ b/examples/cxx/parser/multiroot/protocol-pimpl-tiein.hxx @@ -0,0 +1,55 @@ +// file : examples/cxx/parser/multiroot/protocol-pimpl-tiein.hxx +// author : Boris Kolpackov +// copyright : not copyrighted - public domain + +#ifndef PROTOCOL_PIMPL_HXX +#define PROTOCOL_PIMPL_HXX + +#include "protocol.hxx" +#include "protocol-pskel.hxx" + +namespace protocol +{ + class request_pimpl: public request_pskel + { + public: + virtual void + account (unsigned int); + + virtual request* + post_request (); + + public: + unsigned int account_; + }; + + class balance_pimpl: public balance_pskel + { + public: + balance_pimpl (); + + virtual balance* + post_balance (); + + private: + request_pimpl base_impl_; + }; + + class withdraw_pimpl: public withdraw_pskel + { + public: + withdraw_pimpl (); + + virtual void + amount (unsigned int); + + virtual withdraw* + post_withdraw (); + + private: + request_pimpl base_impl_; + unsigned int amount_; + }; +} + +#endif // PROTOCOL_PIMPL_HXX diff --git a/examples/cxx/parser/multiroot/protocol.hxx b/examples/cxx/parser/multiroot/protocol.hxx new file mode 100644 index 0000000..f076140 --- /dev/null +++ b/examples/cxx/parser/multiroot/protocol.hxx @@ -0,0 +1,62 @@ +// file : examples/cxx/parser/multiroot/protocol.hxx +// author : Boris Kolpackov +// copyright : not copyrighted - public domain + +#ifndef PROTOCOL_HXX +#define PROTOCOL_HXX + +namespace protocol +{ + class request + { + public: + virtual + ~request () + { + } + + unsigned int + account () const + { + return account_; + } + + protected: + request (unsigned int account) + : account_ (account) + { + } + + private: + unsigned int account_; + }; + + class balance: public request + { + public: + balance (unsigned int account) + : request (account) + { + } + }; + + class withdraw: public request + { + public: + withdraw (unsigned int account, unsigned int amount) + : request (account), amount_ (amount) + { + } + + unsigned int + amount () const + { + return amount_; + } + + private: + unsigned int amount_; + }; +} + +#endif // PROTOCOL_HXX diff --git a/examples/cxx/parser/multiroot/protocol.map b/examples/cxx/parser/multiroot/protocol.map new file mode 100644 index 0000000..43c0f21 --- /dev/null +++ b/examples/cxx/parser/multiroot/protocol.map @@ -0,0 +1,12 @@ +# file : examples/cxx/parser/multiroot/protocol.map +# author : Boris Kolpackov +# copyright : not copyrighted - public domain + +namespace http://www.codesynthesis.com/protocol protocol +{ + include "protocol.hxx"; + + request request*; + balance balance*; + withdraw withdraw*; +} diff --git a/examples/cxx/parser/multiroot/protocol.xsd b/examples/cxx/parser/multiroot/protocol.xsd new file mode 100644 index 0000000..4b29926 --- /dev/null +++ b/examples/cxx/parser/multiroot/protocol.xsd @@ -0,0 +1,51 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/examples/cxx/parser/multiroot/withdraw.xml b/examples/cxx/parser/multiroot/withdraw.xml new file mode 100644 index 0000000..7a80aa7 --- /dev/null +++ b/examples/cxx/parser/multiroot/withdraw.xml @@ -0,0 +1,18 @@ + + + + + + + 123456789 + 1000000 + + diff --git a/examples/cxx/parser/polymorphism/README b/examples/cxx/parser/polymorphism/README new file mode 100644 index 0000000..0b3d749 --- /dev/null +++ b/examples/cxx/parser/polymorphism/README @@ -0,0 +1,38 @@ +This example shows how to handle XML Schema polymorphism features such +as xsi:type attributes and substitution groups in the Embedded C++/Parser +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.xml + Sample XML instance document. + +supermen-pskel.hxx +supermen-pskel.cxx + Parser skeletons generated by the XSD/e compiler from supermen.xsd. + Note the use of the --generate-polymorphic command line option. + +supermen-pimpl-mixin.hxx +supermen-pimpl-mixin.cxx + +supermen-pimpl-tiein.hxx +supermen-pimpl-tiein.cxx + Parser implementations (using either mixin or tiein parser reuse + style) that print the XML data to STDOUT. + +driver.cxx + Driver for the example. It first constructs a parser instance from + all the individual parsers found in one of supermen-pimpl-*.hxx. It + then invokes this parser instance to parse the input file. + +To run the example on the sample XML instance document simply execute: + +$ ./driver supermen.xml + +The example reads from STDIN if input file is not specified: + +$ ./driver +// copyright : not copyrighted - public domain + +#include + +#include "supermen-pskel.hxx" // Get the configuration macros (XSDE_*). + +#if defined(XSDE_REUSE_STYLE_MIXIN) +# include "supermen-pimpl-mixin.hxx" +#elif defined(XSDE_REUSE_STYLE_TIEIN) +# include "supermen-pimpl-tiein.hxx" +#else +# error this example requires mixin or tiein parser reuse support +#endif + +using std::cerr; +using std::endl; + +int +main (int argc, char* argv[]) +{ + // Check that the load in substitution and inheritance hashmaps + // is not too high. + // +#ifndef NDEBUG + float load = (float) xml_schema::parser_smap_elements (); + load /= xml_schema::parser_smap_buckets (); + + if (load > 0.8) + { + cerr << "substitution hashmap load is " << load << endl; + cerr << "time to increase XSDE_PARSER_SMAP_BUCKETS" << endl; + } + +#ifdef XSDE_PARSER_VALIDATION + load = (float) xml_schema::parser_imap_elements (); + load /= xml_schema::parser_imap_buckets (); + + if (load > 0.8) + { + cerr << "inheritance hashmap load is " << load << endl; + cerr << "time to increase XSDE_PARSER_IMAP_BUCKETS" << endl; + } +#endif +#endif + + const char* input; + + if (argc < 2) + { + input = "STDIN"; + cerr << "XML file not specified, reading from STDIN" << endl; + } + else + input = argv[1]; + + try + { + // Construct the parser. + // + xml_schema::string_pimpl string_p; + xml_schema::boolean_pimpl boolean_p; + xml_schema::unsigned_int_pimpl unsigned_int_p; + + person_pimpl person_p; + superman_pimpl superman_p; + batman_pimpl batman_p; + + xml_schema::parser_map_impl person_map (5); // 5 hashtable buckets + supermen_pimpl supermen_p; + + + person_p.parsers (string_p); + superman_p.parsers (string_p, boolean_p); + batman_p.parsers (string_p, boolean_p, unsigned_int_p); + + // Here we are specifying several parsers that can be + // used to parse the person element. + // + person_map.insert (person_p); + person_map.insert (superman_p); + person_map.insert (batman_p); + + supermen_p.person_parser (person_map); + + // Parse the XML document. The last argument to the document's + // constructor indicates that we are parsing polymorphic XML + // documents. + // + xml_schema::document_pimpl doc_p (supermen_p, "supermen", true); + + supermen_p.pre (); + + if (argc < 2) + doc_p.parse (std::cin); + else + doc_p.parse (argv[1]); + + supermen_p.post_supermen (); + } + catch (const xml_schema::parser_exception& e) + { + cerr << input << ":" << e.line () << ":" << e.column () << ": " + << e.text () << endl; + return 1; + } + catch (const std::ios_base::failure&) + { + cerr << input << ": unable to open or read failure" << endl; + return 1; + } + + return 0; +} diff --git a/examples/cxx/parser/polymorphism/makefile b/examples/cxx/parser/polymorphism/makefile new file mode 100644 index 0000000..c096e5a --- /dev/null +++ b/examples/cxx/parser/polymorphism/makefile @@ -0,0 +1,71 @@ +# file : examples/cxx/parser/polymorphism/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 := supermen.xsd +cxx := driver.cxx + +ifeq ($(xsde_reuse_style),mixin) +cxx += supermen-pimpl-mixin.cxx +else +cxx += supermen-pimpl-tiein.cxx +endif + +obj := $(addprefix $(out_base)/,$(cxx:.cxx=.o) $(xsd:.xsd=-pskel.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=-pskel.hxx) \ + $(out_base)/$(xsd:.xsd=-pskel.ixx) \ + $(out_base)/$(xsd:.xsd=-pskel.cxx) + +$(skel): xsde := $(out_root)/xsde/xsde +$(skel): xsde_options += --generate-polymorphic +$(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=-pskel.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/parser/xsd-cxx.make) + + +# Dependencies. +# +$(call import,$(src_root)/xsde/makefile) +$(call import,$(src_root)/libxsde/xsde/makefile) diff --git a/examples/cxx/parser/polymorphism/supermen-pimpl-mixin.cxx b/examples/cxx/parser/polymorphism/supermen-pimpl-mixin.cxx new file mode 100644 index 0000000..e8fa8e4 --- /dev/null +++ b/examples/cxx/parser/polymorphism/supermen-pimpl-mixin.cxx @@ -0,0 +1,86 @@ +// file : examples/cxx/parser/polymorphism/supermen-pimpl-mixin.cxx +// author : Boris Kolpackov +// copyright : not copyrighted - public domain +// + +#include + +#include "supermen-pimpl-mixin.hxx" + +using std::cout; +using std::endl; + +// person_pimpl +// +void person_pimpl:: +pre () +{ + cout << "starting to parse person" << endl; +} + +void person_pimpl:: +name (const std::string& v) +{ + cout << "name: " << v << endl; +} + +void person_pimpl:: +post_person () +{ + cout << "finished parsing person" << endl + << endl; +} + +// superman_pimpl +// +void superman_pimpl:: +pre () +{ + cout << "strarting to parse superman" << endl; +} + +void superman_pimpl:: +can_fly (bool v) +{ + cout << "can-fly: " << v << endl; +} + +void superman_pimpl:: +post_person () +{ + post_superman (); +} + +void superman_pimpl:: +post_superman () +{ + cout << "finished parsing superman" << endl + << endl; +} + +// batman_pimpl +// +void batman_pimpl:: +pre () +{ + cout << "starting to parse batman" << endl; +} + +void batman_pimpl:: +wing_span (unsigned int v) +{ + cout << "wing-span: " << v << endl; +} + +void batman_pimpl:: +post_superman () +{ + post_batman (); +} + +void batman_pimpl:: +post_batman () +{ + cout << "finished parsing batman" << endl + << endl; +} diff --git a/examples/cxx/parser/polymorphism/supermen-pimpl-mixin.hxx b/examples/cxx/parser/polymorphism/supermen-pimpl-mixin.hxx new file mode 100644 index 0000000..d07215e --- /dev/null +++ b/examples/cxx/parser/polymorphism/supermen-pimpl-mixin.hxx @@ -0,0 +1,69 @@ +// file : examples/cxx/parser/polymorphism/supermen-pimpl-mixin.hxx +// author : Boris Kolpackov +// copyright : not copyrighted - public domain + +#ifndef SUPERMEN_PIMPL_HXX +#define SUPERMEN_PIMPL_HXX + +#include "supermen-pskel.hxx" + +class person_pimpl: public virtual person_pskel +{ +public: + virtual void + pre (); + + virtual void + name (const std::string&); + + virtual void + post_person (); +}; + +class superman_pimpl: public virtual superman_pskel, + public person_pimpl +{ +public: + virtual void + pre (); + + virtual void + can_fly (bool); + + // By default, post_superman() calls post_person(). In case of + // polymorphic parsing we want the opposite: post_person() calls + // post_superman(). + // + virtual void + post_person (); + + virtual void + post_superman (); +}; + +class batman_pimpl: public virtual batman_pskel, + public superman_pimpl +{ +public: + virtual void + pre (); + + virtual void + wing_span (unsigned int); + + // By default, post_batman() calls post_superman(). In case of + // polymorphic parsing we want the opposite: post_superman() + // calls post_batman(). + // + virtual void + post_superman (); + + virtual void + post_batman (); +}; + +class supermen_pimpl: public virtual supermen_pskel +{ +}; + +#endif // SUPERMEN_PIMPL_HXX diff --git a/examples/cxx/parser/polymorphism/supermen-pimpl-tiein.cxx b/examples/cxx/parser/polymorphism/supermen-pimpl-tiein.cxx new file mode 100644 index 0000000..cb9ece3 --- /dev/null +++ b/examples/cxx/parser/polymorphism/supermen-pimpl-tiein.cxx @@ -0,0 +1,104 @@ +// file : examples/cxx/parser/polymorphism/supermen-pimpl-tiein.cxx +// author : Boris Kolpackov +// copyright : not copyrighted - public domain +// + +#include + +#include "supermen-pimpl-tiein.hxx" + +using std::cout; +using std::endl; + +// person_pimpl +// +void person_pimpl:: +pre () +{ + cout << "starting to parse person" << endl; +} + +void person_pimpl:: +name (const std::string& v) +{ + cout << "name: " << v << endl; +} + +void person_pimpl:: +post_person () +{ + cout << "finished parsing person" << endl + << endl; +} + +// superman_pimpl +// +superman_pimpl:: +superman_pimpl () + : superman_pskel (&base_impl_) +{ +} + +void superman_pimpl:: +pre () +{ + cout << "starting to parse superman" << endl; +} + +void superman_pimpl:: +can_fly (bool v) +{ + cout << "can-fly: " << v << endl; +} + +void superman_pimpl:: +post_person () +{ + post_superman (); +} + +void superman_pimpl:: +post_superman () +{ + cout << "finished parsing superman" << endl + << endl; +} + +// batman_pimpl +// +batman_pimpl:: +batman_pimpl () + : batman_pskel (&base_impl_) +{ +} + +void batman_pimpl:: +pre () +{ + cout << "starting to parse batman" << endl; +} + +void batman_pimpl:: +wing_span (unsigned int v) +{ + cout << "wing-span: " << v << endl; +} + +void batman_pimpl:: +post_person () +{ + post_superman (); +} + +void batman_pimpl:: +post_superman () +{ + post_batman (); +} + +void batman_pimpl:: +post_batman () +{ + cout << "finished parsing batman" << endl + << endl; +} diff --git a/examples/cxx/parser/polymorphism/supermen-pimpl-tiein.hxx b/examples/cxx/parser/polymorphism/supermen-pimpl-tiein.hxx new file mode 100644 index 0000000..b8acd74 --- /dev/null +++ b/examples/cxx/parser/polymorphism/supermen-pimpl-tiein.hxx @@ -0,0 +1,81 @@ +// file : examples/cxx/parser/polymorphism/supermen-pimpl-tiein.hxx +// author : Boris Kolpackov +// copyright : not copyrighted - public domain + +#ifndef SUPERMEN_PIMPL_HXX +#define SUPERMEN_PIMPL_HXX + +#include "supermen-pskel.hxx" + +class person_pimpl: public person_pskel +{ +public: + virtual void + pre (); + + virtual void + name (const std::string&); + + virtual void + post_person (); +}; + +class superman_pimpl: public superman_pskel +{ +public: + superman_pimpl (); + + virtual void + pre (); + + virtual void + can_fly (bool); + + // By default, post_superman() calls post_person(). In case of + // polymorphic parsing we want the opposite: post_person() calls + // post_superman(). + // + virtual void + post_person (); + + virtual void + post_superman (); + +private: + person_pimpl base_impl_; +}; + +class batman_pimpl: public batman_pskel +{ +public: + batman_pimpl (); + + virtual void + pre (); + + virtual void + wing_span (unsigned int); + + // By default, post_batman() calls post_superman() which calls + // post_person(). In case of polymorphic parsing we want the + // opposite: post_person() calls post_superman() which calls + // post_batman(). + // + virtual void + post_person (); + + virtual void + post_superman (); + + virtual void + post_batman (); + +private: + superman_pimpl base_impl_; +}; + +class supermen_pimpl: public virtual supermen_pskel +{ +}; + +#endif // SUPERMEN_PIMPL_HXX diff --git a/examples/cxx/parser/polymorphism/supermen.xml b/examples/cxx/parser/polymorphism/supermen.xml new file mode 100644 index 0000000..2d73c44 --- /dev/null +++ b/examples/cxx/parser/polymorphism/supermen.xml @@ -0,0 +1,26 @@ + + + + + + + + John Doe + + + + James "007" Bond + + + + Bruce Wayne + + + diff --git a/examples/cxx/parser/polymorphism/supermen.xsd b/examples/cxx/parser/polymorphism/supermen.xsd new file mode 100644 index 0000000..83a7aac --- /dev/null +++ b/examples/cxx/parser/polymorphism/supermen.xsd @@ -0,0 +1,49 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/examples/cxx/parser/polyroot/README b/examples/cxx/parser/polyroot/README new file mode 100644 index 0000000..4b01b56 --- /dev/null +++ b/examples/cxx/parser/polyroot/README @@ -0,0 +1,47 @@ +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++/Parser mapping see the +polymorphism example. + +The example consists of the following files: + +supermen.xsd + XML Schema which describes supermen instance documents. + +person.xml +superman.xml +batman.xml + Sample XML instance documents. + +supermen-pskel.hxx +supermen-pskel.cxx + Parser skeletons generated by the XSD/e compiler from supermen.xsd. + Note the use of the --generate-polymorphic command line option. + +supermen-pimpl-mixin.hxx +supermen-pimpl-mixin.cxx + +supermen-pimpl-tiein.hxx +supermen-pimpl-tiein.cxx + Parser implementations (using either mixin or tiein parser reuse + style) that print the XML data to STDOUT. + +driver.cxx + Driver for the example. It implements a custom document parser + that determines which XML Schema type is being parsed and uses + the corresponding parser implementation. The driver first + constructs a parser instance from all the individual parsers + found in one of supermen-pimpl-*.hxx. In then invokes this parser + instance to parse the input file. + +To run the example on the sample XML instance documents simply execute: + +$ ./driver person.xml +$ ./driver superman.xml +$ ./driver batman.xml + +The example reads from STDIN if input file is not specified: + +$ ./driver + + + + + + Bruce Wayne + + diff --git a/examples/cxx/parser/polyroot/driver.cxx b/examples/cxx/parser/polyroot/driver.cxx new file mode 100644 index 0000000..592ccfd --- /dev/null +++ b/examples/cxx/parser/polyroot/driver.cxx @@ -0,0 +1,216 @@ +// file : examples/cxx/parser/polyroot/driver.cxx +// author : Boris Kolpackov +// copyright : not copyrighted - public domain + +#include + +#include "supermen-pskel.hxx" // Get the configuration macros (XSDE_*). + +#if defined(XSDE_REUSE_STYLE_MIXIN) +# include "supermen-pimpl-mixin.hxx" +#elif defined(XSDE_REUSE_STYLE_TIEIN) +# include "supermen-pimpl-tiein.hxx" +#else +# error this example requires mixin or tiein parser reuse support +#endif + +using std::cerr; +using std::endl; +using xml_schema::ro_string; + +// Customize the xml_schema::document object to handle polymorphic +// root element. For more information see the multiroot example. +// +class document_pimpl: public xml_schema::document_pimpl +{ +public: + // Passing the root element name to xml_schema::document_pimpl + // constructor indicates that we are doing polymorphic parsing. + // The root element name is used to automatically translate + // substitutions to type information. + // + document_pimpl (xml_schema::parser_map& parser_map) + : xml_schema::document_pimpl ("person"), + parser_map_ (parser_map), + parser_used_ (0) + { + } + +protected: + // This function is called to obtain the root element type parser. + // If the returned pointer is 0 then the whole document content + // is ignored. The type argument contains the XML Schema type + // if xsi:type attribute or an element that substitutes the root + // was specified and 0 otherwise. + // + virtual xml_schema::parser_base* + start_root_element (const ro_string& ns, + const ro_string& name, + const char* type) + { + if (name != "person" || !ns.empty ()) + { + // If the runtime and the generated code are built with + // validation enabled then we can also set an XML Schema + // error. + // +#ifdef XSDE_PARSER_VALIDATION + context_.schema_error ( + xml_schema::parser_schema_error::unexpected_element); +#endif + return 0; + } + + // Search the parser map. If type is 0 then there is no xsi:type and + // static type should be used. + // + xml_schema::parser_base* p = parser_map_.find ( + type ? type : person_pskel::_static_type ()); + + if (p != 0) + { + // The map returns a generic parser_base which we will cast to + // person_pskel in order to call the pre() and post_person() + // callbacks. If the runtime and the generated code are built + // with the mixin parser reuse style then we have to use + // dynamic_cast because of the virtual inheritance. + // +#ifdef XSDE_REUSE_STYLE_MIXIN + parser_used_ = dynamic_cast (p); +#else + parser_used_ = static_cast (p); +#endif + parser_used_->pre (); + } + else + { + // No parser for this type. We could also make this an error + // by calling the schema_error() function as above. + // + parser_used_ = 0; + } + + return p; + } + + // This function is called to indicate the completion of document + // parsing. The parser argument contains the pointer returned by + // start_root_element. + // + virtual void + end_root_element (const ro_string& /* ns */, + const ro_string& /* name */, + xml_schema::parser_base* /* parser */) + { + // Instead of caching the current parser in parser_used_, we + // could also cast the parser argument to the person_pskel + // type. + // + if (parser_used_) + parser_used_->post_person (); + } + +public: + // 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 parser that was used last. Note that you always need + // to call _reset() from the base. + // + virtual void + reset () + { + xml_schema::document_pimpl::reset (); + + if (parser_used_) + parser_used_->_reset (); + } + +private: + xml_schema::parser_map& parser_map_; + person_pskel* parser_used_; +}; + +int +main (int argc, char* argv[]) +{ + // Check that the load in substitution and inheritance hashmaps + // is not too high. + // +#ifndef NDEBUG + float load = (float) xml_schema::parser_smap_elements (); + load /= xml_schema::parser_smap_buckets (); + + if (load > 0.8) + { + cerr << "substitution hashmap load is " << load << endl; + cerr << "time to increase XSDE_PARSER_SMAP_BUCKETS" << endl; + } + +#ifdef XSDE_PARSER_VALIDATION + load = (float) xml_schema::parser_imap_elements (); + load /= xml_schema::parser_imap_buckets (); + + if (load > 0.8) + { + cerr << "inheritance hashmap load is " << load << endl; + cerr << "time to increase XSDE_PARSER_IMAP_BUCKETS" << endl; + } +#endif +#endif + + const char* input; + + if (argc < 2) + { + input = "STDIN"; + cerr << "XML file not specified, reading from STDIN" << endl; + } + else + input = argv[1]; + + try + { + // Construct the parser. + // + xml_schema::string_pimpl string_p; + xml_schema::boolean_pimpl boolean_p; + xml_schema::unsigned_int_pimpl unsigned_int_p; + + person_pimpl person_p; + superman_pimpl superman_p; + batman_pimpl batman_p; + + person_p.parsers (string_p); + superman_p.parsers (string_p, boolean_p); + batman_p.parsers (string_p, boolean_p, unsigned_int_p); + + // Parse the XML document. + // + xml_schema::parser_map_impl person_map (5); // 5 hashtable buckets + + person_map.insert (person_p); + person_map.insert (superman_p); + person_map.insert (batman_p); + + document_pimpl doc_p (person_map); + + // pre() and post() will be called as part of the start_root_element() + // and end_root_element() calls. + // + if (argc < 2) + doc_p.parse (std::cin); + else + doc_p.parse (argv[1]); + } + catch (const xml_schema::parser_exception& e) + { + cerr << input << ":" << e.line () << ":" << e.column () << ": " + << e.text () << endl; + return 1; + } + catch (const std::ios_base::failure&) + { + cerr << input << ": unable to open or read failure" << endl; + return 1; + } +} diff --git a/examples/cxx/parser/polyroot/makefile b/examples/cxx/parser/polyroot/makefile new file mode 100644 index 0000000..0f4d6eb --- /dev/null +++ b/examples/cxx/parser/polyroot/makefile @@ -0,0 +1,71 @@ +# file : examples/cxx/parser/polyroot/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 := supermen.xsd +cxx := driver.cxx + +ifeq ($(xsde_reuse_style),mixin) +cxx += supermen-pimpl-mixin.cxx +else +cxx += supermen-pimpl-tiein.cxx +endif + +obj := $(addprefix $(out_base)/,$(cxx:.cxx=.o) $(xsd:.xsd=-pskel.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=-pskel.hxx) \ + $(out_base)/$(xsd:.xsd=-pskel.ixx) \ + $(out_base)/$(xsd:.xsd=-pskel.cxx) + +$(skel): xsde := $(out_root)/xsde/xsde +$(skel): xsde_options += --generate-polymorphic +$(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=-pskel.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/parser/xsd-cxx.make) + + +# Dependencies. +# +$(call import,$(src_root)/xsde/makefile) +$(call import,$(src_root)/libxsde/xsde/makefile) diff --git a/examples/cxx/parser/polyroot/person.xml b/examples/cxx/parser/polyroot/person.xml new file mode 100644 index 0000000..157a5af --- /dev/null +++ b/examples/cxx/parser/polyroot/person.xml @@ -0,0 +1,16 @@ + + + + + + + John Doe + + diff --git a/examples/cxx/parser/polyroot/superman.xml b/examples/cxx/parser/polyroot/superman.xml new file mode 100644 index 0000000..0f4b89c --- /dev/null +++ b/examples/cxx/parser/polyroot/superman.xml @@ -0,0 +1,17 @@ + + + + + + + James "007" Bond + + diff --git a/examples/cxx/parser/polyroot/supermen-pimpl-mixin.cxx b/examples/cxx/parser/polyroot/supermen-pimpl-mixin.cxx new file mode 100644 index 0000000..fb339ac --- /dev/null +++ b/examples/cxx/parser/polyroot/supermen-pimpl-mixin.cxx @@ -0,0 +1,83 @@ +// file : examples/cxx/parser/polyroot/supermen-pimpl-mixin.cxx +// author : Boris Kolpackov +// copyright : not copyrighted - public domain +// + +#include + +#include "supermen-pimpl-mixin.hxx" + +using std::cout; +using std::endl; + +// person_pimpl +// +void person_pimpl:: +pre () +{ + cout << "starting to parse person" << endl; +} + +void person_pimpl:: +name (const std::string& v) +{ + cout << "name: " << v << endl; +} + +void person_pimpl:: +post_person () +{ + cout << "finished parsing person" << endl; +} + +// superman_pimpl +// +void superman_pimpl:: +pre () +{ + cout << "starting to parse superman" << endl; +} + +void superman_pimpl:: +can_fly (bool v) +{ + cout << "can-fly: " << v << endl; +} + +void superman_pimpl:: +post_person () +{ + post_superman (); +} + +void superman_pimpl:: +post_superman () +{ + cout << "finished parsing superman" << endl; +} + +// batman_pimpl +// +void batman_pimpl:: +pre () +{ + cout << "starting to parse batman" << endl; +} + +void batman_pimpl:: +wing_span (unsigned int v) +{ + cout << "wing-span: " << v << endl; +} + +void batman_pimpl:: +post_superman () +{ + post_batman (); +} + +void batman_pimpl:: +post_batman () +{ + cout << "finished parsing batman" << endl; +} diff --git a/examples/cxx/parser/polyroot/supermen-pimpl-mixin.hxx b/examples/cxx/parser/polyroot/supermen-pimpl-mixin.hxx new file mode 100644 index 0000000..1f66062 --- /dev/null +++ b/examples/cxx/parser/polyroot/supermen-pimpl-mixin.hxx @@ -0,0 +1,65 @@ +// file : examples/cxx/parser/polyroot/supermen-pimpl-mixin.hxx +// author : Boris Kolpackov +// copyright : not copyrighted - public domain + +#ifndef SUPERMEN_PIMPL_HXX +#define SUPERMEN_PIMPL_HXX + +#include "supermen-pskel.hxx" + +class person_pimpl: public virtual person_pskel +{ +public: + virtual void + pre (); + + virtual void + name (const std::string&); + + virtual void + post_person (); +}; + +class superman_pimpl: public virtual superman_pskel, + public person_pimpl +{ +public: + virtual void + pre (); + + virtual void + can_fly (bool); + + // By default, post_superman() calls post_person(). In case of + // polymorphic parsing we want the opposite: post_person() calls + // post_superman(). + // + virtual void + post_person (); + + virtual void + post_superman (); +}; + +class batman_pimpl: public virtual batman_pskel, + public superman_pimpl +{ +public: + virtual void + pre (); + + virtual void + wing_span (unsigned int); + + // By default, post_batman() calls post_superman(). In case of + // polymorphic parsing we want the opposite: post_superman() + // calls post_batman(). + // + virtual void + post_superman (); + + virtual void + post_batman (); +}; + +#endif // SUPERMEN_PIMPL_HXX diff --git a/examples/cxx/parser/polyroot/supermen-pimpl-tiein.cxx b/examples/cxx/parser/polyroot/supermen-pimpl-tiein.cxx new file mode 100644 index 0000000..b02eeef --- /dev/null +++ b/examples/cxx/parser/polyroot/supermen-pimpl-tiein.cxx @@ -0,0 +1,101 @@ +// file : examples/cxx/parser/polyroot/supermen-pimpl-tiein.cxx +// author : Boris Kolpackov +// copyright : not copyrighted - public domain +// + +#include + +#include "supermen-pimpl-tiein.hxx" + +using std::cout; +using std::endl; + +// person_pimpl +// +void person_pimpl:: +pre () +{ + cout << "starting to parse person" << endl; +} + +void person_pimpl:: +name (const std::string& v) +{ + cout << "name: " << v << endl; +} + +void person_pimpl:: +post_person () +{ + cout << "finished parsing person" << endl; +} + +// superman_pimpl +// +superman_pimpl:: +superman_pimpl () + : superman_pskel (&base_impl_) +{ +} + +void superman_pimpl:: +pre () +{ + cout << "starting to parse superman" << endl; +} + +void superman_pimpl:: +can_fly (bool v) +{ + cout << "can-fly: " << v << endl; +} + +void superman_pimpl:: +post_person () +{ + post_superman (); +} + +void superman_pimpl:: +post_superman () +{ + cout << "finished parsing superman" << endl; +} + +// batman_pimpl +// +batman_pimpl:: +batman_pimpl () + : batman_pskel (&base_impl_) +{ +} + +void batman_pimpl:: +pre () +{ + cout << "starting to parse batman" << endl; +} + +void batman_pimpl:: +wing_span (unsigned int v) +{ + cout << "wing-span: " << v << endl; +} + +void batman_pimpl:: +post_person () +{ + post_superman (); +} + +void batman_pimpl:: +post_superman () +{ + post_batman (); +} + +void batman_pimpl:: +post_batman () +{ + cout << "finished parsing batman" << endl; +} diff --git a/examples/cxx/parser/polyroot/supermen-pimpl-tiein.hxx b/examples/cxx/parser/polyroot/supermen-pimpl-tiein.hxx new file mode 100644 index 0000000..41dfe84 --- /dev/null +++ b/examples/cxx/parser/polyroot/supermen-pimpl-tiein.hxx @@ -0,0 +1,77 @@ +// file : examples/cxx/parser/polyroot/supermen-pimpl-tiein.hxx +// author : Boris Kolpackov +// copyright : not copyrighted - public domain + +#ifndef SUPERMEN_PIMPL_HXX +#define SUPERMEN_PIMPL_HXX + +#include "supermen-pskel.hxx" + +class person_pimpl: public person_pskel +{ +public: + virtual void + pre (); + + virtual void + name (const std::string&); + + virtual void + post_person (); +}; + +class superman_pimpl: public superman_pskel +{ +public: + superman_pimpl (); + + virtual void + pre (); + + virtual void + can_fly (bool); + + // By default, post_superman() calls post_person(). In case of + // polymorphic parsing we want the opposite: post_person() calls + // post_superman(). + // + virtual void + post_person (); + + virtual void + post_superman (); + +private: + person_pimpl base_impl_; +}; + +class batman_pimpl: public batman_pskel +{ +public: + batman_pimpl (); + + virtual void + pre (); + + virtual void + wing_span (unsigned int); + + // By default, post_batman() calls post_superman() which calls + // post_person(). In case of polymorphic parsing we want the + // opposite: post_person() calls post_superman() which calls + // post_batman(). + // + virtual void + post_person (); + + virtual void + post_superman (); + + virtual void + post_batman (); + +private: + superman_pimpl base_impl_; +}; + +#endif // SUPERMEN_PIMPL_HXX diff --git a/examples/cxx/parser/polyroot/supermen.xsd b/examples/cxx/parser/polyroot/supermen.xsd new file mode 100644 index 0000000..722d59b --- /dev/null +++ b/examples/cxx/parser/polyroot/supermen.xsd @@ -0,0 +1,40 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/examples/cxx/parser/wildcard/README b/examples/cxx/parser/wildcard/README new file mode 100644 index 0000000..d978ddc --- /dev/null +++ b/examples/cxx/parser/wildcard/README @@ -0,0 +1,33 @@ +This example shows how to parse XML data matched by XML Schema +wildcards (any and anyAttribute) using the Embedded C++/Parser +mapping. + +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-pskel.hxx +email-pskel.cxx + Parser skeletons generated by XSD/e from email.xsd. + +driver.cxx + Parser implementations and a driver for the example. The + parser implementations simply print the data to STDERR. + The driver first constructs parser instances from the + parser implementations mentioned above and a couple of + predefined parsers for the XML Schema built-in types. + In then invokes the parser instances to parse the input + file. + +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 +#include +#include + +#include "email-pskel.hxx" + +#ifndef XSDE_REUSE_STYLE_TIEIN +# error this example requires the tiein parser reuse support +#endif + +using namespace std; +using xml_schema::ro_string; + +namespace email +{ + class binary_pimpl: public binary_pskel + { + public: + binary_pimpl () + : binary_pskel (&base_impl_) + { + } + + virtual void + name (const string& n) + { + cerr << "binary: " << n << endl; + } + + virtual void + mime (const string& t) + { + cerr << "type: " << t << endl; + } + + virtual void + post_binary () + { + std::auto_ptr buf (post_base64_binary ()); + + cerr << "size: " << buf->size () << endl + << endl; + } + + private: + xml_schema::base64_binary_pimpl base_impl_; + }; + + class envelope_pimpl: public envelope_pskel + { + public: + envelope_pimpl (xml_schema::unsigned_int_pskel& uint_p, + xml_schema::string_pskel& string_p, + binary_pskel& binary_p) + : depth_ (0), + uint_p_ (uint_p), string_p_ (string_p), binary_p_ (binary_p) + { + } + + virtual void + to (const string& addr) + { + cerr << "To: " << addr << endl; + } + + virtual void + from (const string& addr) + { + cerr << "From: " << addr << endl; + } + + virtual void + subject (const string& s) + { + cerr << "Subject: " << s << endl; + } + + // Wildcard handling. 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(), clean up, etc. + // + // 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. + // + // Finally, 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. + // + virtual void +#ifndef XSDE_POLYMORPHIC + _start_any_element (const ro_string& ns, const ro_string& name) +#else + _start_any_element (const ro_string& ns, + const 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 = &string_p_; + } + else if (name == "binary") + { + p = &binary_p_; + } + + if (p != 0) + { + xml_schema::parser_context& ctx = _context (); + + p->pre (); + +#ifndef XSDE_EXCEPTIONS + if (p->_error_type ()) + { + // Propagate the error. + // + p->_copy_error (ctx); + return; + } +#endif + p->_pre_impl (ctx); + } + } + + if (p == 0) + { + cerr << "Unknown wildcard content: " << ns << "#" << name << endl; + } + } + } + + virtual void + _end_any_element (const ro_string& ns, const ro_string& name) + { + if (--depth_ == 0) + { + if (ns == "http://www.codesynthesis.com/email") + { + if (name == "text") + { + // Note that we don't call _post_impl() (corresponding to + // _pre_impl()) here. It is called automatically by the + // infrastructure. + // + + string text (string_p_.post_string ()); + +#ifndef XSDE_EXCEPTIONS + if (string_p_._error_type ()) + { + // Propagate the error. + // + string_p_._copy_error (_context ()); + return; + } +#endif + cerr << text << endl + << endl; + } + else if (name == "binary") + { + // Note that we don't call _post_impl() (corresponding to + // _pre_impl()) here. It is called automatically by the + // infrastructure. + // + + binary_p_.post_binary (); + +#ifndef XSDE_EXCEPTIONS + if (binary_p_._error_type ()) + { + // Propagate the error. + // + binary_p_._copy_error (_context ()); + return; + } +#endif + } + } + } + } + + virtual void + _any_attribute (const ro_string& ns, + const ro_string& name, + const ro_string& value) + { + if (depth_ == 0) + { + // Top-level (relative to this type) attribute matched by the + // anyAttribute wildcard. + // + if (ns == "http://www.codesynthesis.com/email" && name == "thread-id") + { + xml_schema::parser_context& ctx = _context (); + + uint_p_.pre (); + +#ifndef XSDE_EXCEPTIONS + if (uint_p_._error_type ()) + { + uint_p_._copy_error (ctx); + return; + } +#endif + + uint_p_._pre_impl (ctx); + +#if defined(XSDE_PARSER_VALIDATION) || !defined(XSDE_EXCEPTIONS) + if (ctx.error_type ()) + return; +#endif + + uint_p_._characters (value); + +#if defined(XSDE_PARSER_VALIDATION) || !defined(XSDE_EXCEPTIONS) + if (ctx.error_type ()) + return; +#endif + + uint_p_._post_impl (); + +#if defined(XSDE_PARSER_VALIDATION) || !defined(XSDE_EXCEPTIONS) + if (ctx.error_type ()) + return; +#endif + + unsigned int tid = uint_p_.post_unsigned_int (); + +#ifndef XSDE_EXCEPTIONS + if (uint_p_._error_type ()) + { + uint_p_._copy_error (ctx); + return; + } +#endif + + cerr << "Thread-id: " << tid << endl; + } + } + } + + // 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. Note that + // you always need to call _reset() from the base. + // + virtual void + _reset () + { + envelope_pskel::_reset (); + + depth_ = 0; + uint_p_._reset (); + string_p_._reset (); + binary_p_._reset (); + } + + private: + std::size_t depth_; + + // Parsers for the unsigned int, string and binary types. + // + private: + xml_schema::unsigned_int_pskel& uint_p_; + xml_schema::string_pskel& string_p_; + binary_pskel& binary_p_; + }; +} + + +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 + { + // Construct the parser. + // + xml_schema::unsigned_int_pimpl unsigned_int_p; + xml_schema::string_pimpl string_p; + email::binary_pimpl binary_p; + email::envelope_pimpl envelope_p (unsigned_int_p, string_p, binary_p); + + binary_p.parsers (string_p, // name + string_p); // mime + + envelope_p.parsers (string_p, // to + string_p, // from + string_p); // subject + + // Parse the XML instance document. + // + xml_schema::document_pimpl doc_p ( + envelope_p, + "http://www.codesynthesis.com/email", + "message"); + + envelope_p.pre (); + + if (argc < 2) + doc_p.parse (cin); + else + doc_p.parse (argv[1]); + + envelope_p.post_envelope (); + } + catch (const xml_schema::parser_exception& e) + { + cerr << input << ":" << e.line () << ":" << e.column () << ": " + << e.text () << endl; + return 1; + } + catch (const std::ios_base::failure&) + { + cerr << input << ": unable to open or read failure" << endl; + return 1; + } + + return 0; +} diff --git a/examples/cxx/parser/wildcard/email.xml b/examples/cxx/parser/wildcard/email.xml new file mode 100644 index 0000000..55f1e4b --- /dev/null +++ b/examples/cxx/parser/wildcard/email.xml @@ -0,0 +1,32 @@ + + + + + + + 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/parser/wildcard/email.xsd b/examples/cxx/parser/wildcard/email.xsd new file mode 100644 index 0000000..2e1f660 --- /dev/null +++ b/examples/cxx/parser/wildcard/email.xsd @@ -0,0 +1,51 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/examples/cxx/parser/wildcard/makefile b/examples/cxx/parser/wildcard/makefile new file mode 100644 index 0000000..8613847 --- /dev/null +++ b/examples/cxx/parser/wildcard/makefile @@ -0,0 +1,64 @@ +# file : examples/cxx/parser/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=-pskel.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=-pskel.hxx) \ + $(out_base)/$(xsd:.xsd=-pskel.ixx) \ + $(out_base)/$(xsd:.xsd=-pskel.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=-pskel.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/parser/xsd-cxx.make) + + +# Dependencies. +# +$(call import,$(src_root)/xsde/makefile) +$(call import,$(src_root)/libxsde/xsde/makefile) 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 +// copyright : not copyrighted - public domain + +#include +#include +#include + +#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 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 @@ + + + + + + + + + + + + + + + + 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 +# 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 +// copyright : not copyrighted - public domain + +#include + +#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 +// 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 +// 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 +// 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 +// 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 +// copyright : not copyrighted - public domain + +#ifndef LIBRARY_HXX +#define LIBRARY_HXX + +#include +#include + +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 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 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 +# 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 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 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 +# 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 +# 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 +// copyright : not copyrighted - public domain + +#include + +#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 +# 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 +// 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 +// 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 +// copyright : not copyrighted - public domain + +#ifndef PEOPLE_HXX +#define PEOPLE_HXX + +#include // 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 +# 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 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 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 +// copyright : not copyrighted - public domain + +#include + +#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 +# 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 +// 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 (person_)->can_fly (); +} + +// +// +unsigned int batman_simpl:: +wing_span () +{ + return static_cast (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 +// 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 +// 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 (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 (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 +// 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 +// copyright : not copyrighted - public domain + +#ifndef SUPERMEN_HXX +#define SUPERMEN_HXX + +#include +#include + +// 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 +{ + ~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 +# 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 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 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 +// copyright : not copyrighted - public domain + +#include + +#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 +# 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 +// 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 (person_)->can_fly (); +} + +// +// +unsigned int batman_simpl:: +wing_span () +{ + return static_cast (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 +// 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 +// 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 (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 (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 +// 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 +// copyright : not copyrighted - public domain + +#ifndef SUPERMEN_HXX +#define SUPERMEN_HXX + +#include +#include + +// 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 +{ + ~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 +# 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 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 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